hashicorp/agent-skills1 file

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).

Specification
Skill ID
hashicorp/agent-skills/provider-actions
Publisher
hashicorp
Repository
agent-skills
Installs
0
Files
1
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

hashicorp/agent-skills/provider-actionsInstalls these files
  • SKILL.md

What this skill tells the agent

Terraform Provider Actions Implementation Guide

Overview

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:

First Action Setup

When adding the first action to a provider that has never had one, several one-time scaffolding steps are required:

  1. Implement `ProviderWithActions` — add an Actions() method to the provider that returns []func() action.Action.
  2. Set `ActionData` in `Configure` — the provider's Configure method must set resp.ActionData = v alongside the existing ResourceData, DataSourceData, and EphemeralResourceData assignments.
  3. Create `ActionWithConfigure` base type — if the provider uses embedded base types (e.g. ResourceWithConfigure), create an equivalent ActionWithConfigure type implementing action.ConfigureRequest / action.ConfigureResponse.
  4. Action-schema helper variants — if the provider injects common schema attributes (e.g. namespace) via helper functions, action-schema variants are needed since action/schema types differ from resource/schema types.

File Structure

Most providers keep actions alongside resources in the provider package:

internal/provider/
├── <action_name>_action.go       # Action implementation
└── <action_name>_action_test.go  # Action tests

(Large multi-service providers use internal/service/<service>/ packages instead — follow the target repository's layout.)

Documentation lives with the other generated docs:

docs/actions/
└── <action_name>.md              # User-facing documentation

(Some older, large providers hand-write website/docs/actions/<name>.html.markdown instead — match the repo.)

Action Schema Definition

Actions use the Terraform Plugin Framework with a standard schema pattern:

func (a *actionType) Schema(ctx context.Context, req action.SchemaRequest, resp *action.SchemaResponse) {
    resp.Schema = schema.Schema{
        Attributes: map[string]schema.Attribute{
            // Required configuration parameters
            "resource_id": schema.StringAttribute{
                Required:    true,
                Description: "ID of the resource to operate on",
            },
            // Optional parameters with defaults
            "timeout": schema.Int64Attribute{
                Optional:    true,
                Description: "Operation timeout in seconds",
                Default:     int64default.StaticInt64(1800),
                Computed:    true,
            },
        },
    }
}

Common Schema Issues

Pay special attention to the schema definition - common issues after a first draft:

  1. Type Mismatches
  • Model structs use types.String/types.Int64 and schemas use types.StringType from github.com/hashicorp/terraform-plugin-framework/types — don't mix in types from other packages
  • Some large providers layer their own custom type package on top (e.g. terraform-provider-aws's internal fwtypes); inside such a repo, follow its convention consistently instead of the plain types
  1. List/Map Element Types ```go // WRONG - missing ElementType "items": schema.ListAttribute{ Optional: true, }

// CORRECT "items": schema.ListAttribute{ Optional: true, ElementType: types.StringType, }


3. **Computed vs Optional**
   - Attributes with defaults must be both `Optional: true` and `Computed: true`
   - Don't mark action inputs as `Computed` unless they have defaults

4. **Validator Imports**

// Ensure proper imports "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"


5. **Region/Provider Attribute** (multi-region providers, e.g. AWS)
   - Use the provider's shared region handling when it has one
   - Don't manually re-define provider-level configuration in an action schema

6. **Nested Attributes**
   - Use appropriate nested object types for complex structures
   - Ensure nested types are properly defined

### Schema Validation Checklist

Before submitting, verify:
- [ ] All attributes have descriptions
- [ ] List/Map attributes have ElementType defined
- [ ] Validators are imported and applied correctly
- [ ] Model struct uses correct framework types
- [ ] Optional attributes with defaults are marked Computed
- [ ] Code compiles without type errors
- [ ] Run `go build` to catch type mismatches

## Action Invoke Method

The Invoke method contains the action logic:

func (a actionType) Invoke(ctx context.Context, req action.InvokeRequest, resp action.InvokeResponse) { var data actionModel resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) if resp.Diagnostics.HasError() { return }

// a.client was stored by Configure (from req.ProviderData), the same // pattern resources use. resp.SendProgress(action.InvokeProgressEvent{Message: "Starting operation..."})

// Implement action logic with error handling // Use context for timeout management // Poll for completion if async operation

resp.SendProgress(action.InvokeProgressEvent{Message: "Operation completed"}) }


## Key Implementation Requirements

### 1. Progress Reporting

- Use `resp.SendProgress(action.InvokeProgressEvent{...})` for real-time updates
- Provide meaningful progress messages during long operations
- Update progress at key milestones
- Include elapsed time for long operations

### 2. Timeout Management

- Always include configurable timeout parameter (default: 1800s)
- Use `context.WithTimeout()` for API calls
- Handle timeout errors gracefully
- Validate timeout ranges (typically 60-7200 seconds)

### 3. Error Handling

- Add diagnostics with `resp.Diagnostics.AddError()`
- Provide clear error messages with context
- Include API error details when relevant
- Map provider error types to user-friendly messages
- Document all possible error cases

Example error handling:

// Handle specific errors var notFound *types.ResourceNotFoundException if errors.As(err, &notFound) { resp.Diagnostics.AddError( "Resource Not Found", fmt.Sprintf("Resource %s was not found", resourceID), ) return }

// Generic error handling resp.Diagnostics.AddError( "Operation Failed", fmt.Sprintf("Could not complete operation for %s: %s", resourceID, err), )


### 4. Provider SDK Integration

- Use the API client stored at Configure time (`a.client`), shared with
  resources and data sources
- Handle pagination for list operations
- Implement retry logic for transient failures
- Use appropriate error types

### 5. Parameter Validation

- Use framework validators for input validation
- Validate resource existence before operations
- Check for conflicting parameters
- Validate against provider naming requirements

### 6. Polling and Waiting

For 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.)

ctx, cancel := context.WithTimeout(ctx, timeout) defer cancel()

ticker := time.NewTicker(5 * time.Second) defer ticker.Stop()

// Poll fast, report slow: progress events cross the plugin protocol, so // throttle them instead of emitting one per poll. start := time.Now() var lastProgress time.Time for { res, err := findResource(ctx, a.client, id) if err != nil {

Use this skill in a project

Open any RiverX project, search the Skills panel for hashicorp/agent-skills/provider-actions, and install it in one click.

Use this skill