PluginBench
Skill
Fail
Audit score 45

aws-sdk-swift-usage

aws/agent-toolkit-for-aws

AWS SDK for Swift patterns and async client usage for S3, DynamoDB, CloudWatch, and other AWS services.

What is aws-sdk-swift-usage?

Provides Swift development patterns for the aws-sdk-swift package, including async/await client creation, configuration with struct-based types, credential resolvers, and common operations. Use when writing Swift code that integrates with AWS services.

  • Create and configure AWS service clients (S3, DynamoDB, CloudWatch, STS) with struct-based config types
  • Execute async operations with proper error handling and region configuration
  • Implement custom credential resolvers including static credentials and STS assume-role flows
  • Use waiters to poll for resource state changes with configurable timeout
  • Paginate through large result sets with async iteration
  • Generate presigned URLs for secure object access

How to install aws-sdk-swift-usage

npx skills add https://github.com/aws/agent-toolkit-for-aws --skill aws-sdk-swift-usage
Prerequisites
  • aws-sdk-swift package installed via Swift Package Manager
  • Swift 5.7 or later with async/await support
  • AWS credentials configured (via environment, IAM role, or custom resolver)
Claude Code
Cursor
Windsurf
Cline

How to use aws-sdk-swift-usage

  1. 1.Import the appropriate AWS service module (e.g., `import AWSS3`)
  2. 2.Create a service client using `<Service>Client()` with optional region or config struct
  3. 3.Use struct-based config types like `S3Client.S3ClientConfig` (never deprecated class types)
  4. 4.Call async operations with `try await` and handle errors appropriately
  5. 5.For custom credentials, create a credential resolver and pass it to the config
  6. 6.For pagination, use the `<Operation>Paginated` method with async iteration

Use cases

Good for
  • Building Swift applications that read/write objects to S3 buckets
  • Querying and updating DynamoDB tables from Swift code
  • Monitoring CloudWatch metrics and logs from Swift services
  • Assuming IAM roles for cross-account or temporary credential access
  • Generating time-limited presigned URLs for secure file downloads
Who it's for
  • Swift developers building AWS-integrated applications
  • Backend engineers using Swift for AWS Lambda or EC2 workloads
  • DevOps engineers automating AWS operations with Swift scripts
  • Mobile developers accessing AWS services from Swift apps

aws-sdk-swift-usage FAQ

Should I use S3ClientConfiguration or S3Client.S3ClientConfig?

Always use the struct-based config type `S3Client.S3ClientConfig`. The class-based `S3ClientConfiguration` is deprecated and will cause errors.

How do I specify AWS region?

Region is required when creating a config. Pass it as a parameter: `S3Client.S3ClientConfig(region: "us-west-2")` or directly to the client: `S3Client(region: "us-west-2")`.

What order should config parameters be in?

Config parameters must be in declaration order as defined in the service client source. Check `Sources/Services/AWS<Service>/Sources/AWS<Service>/<Service>Client.swift` in the SDK for exact order.

How do I use custom credentials instead of default chain?

Create a credential resolver (StaticAWSCredentialIdentityResolver for static creds, STSAssumeRoleAWSCredentialIdentityResolver for role assumption) and pass it to the config via `awsCredentialIdentityResolver` parameter.

How do I paginate through large result sets?

Use the `<Operation>Paginated` method (e.g., `listObjectsV2Paginated`) and iterate with `for try await page in client.operation(input: input)`.

Full instructions (SKILL.md)

Source of truth, from aws/agent-toolkit-for-aws.


name: aws-sdk-swift-usage description: | AWS SDK for Swift development patterns. Use when writing Swift code that uses AWS services via aws-sdk-swift package.

AWS SDK for Swift

Async Code Structure

All SDK operations are async. Use @main entry point:

@main
struct Main {
    static func main() async throws {
        let client = try await S3Client()
        // ... async operations
    }
}

CRITICAL: Use Struct Config Types

NEVER use S3ClientConfiguration or DynamoDBClientConfiguration - these are DEPRECATED classes.

ALWAYS use the struct-based config types:

  • S3Client.S3ClientConfig (not S3ClientConfiguration)
  • DynamoDBClient.DynamoDBClientConfig (not DynamoDBClientConfiguration)
  • STSClient.STSClientConfig (not STSClientConfiguration)

Config parameters MUST be in declaration order. Region is ALWAYS required when creating a config. Check the service client source for exact order.

// CORRECT - struct config
let config = try await S3Client.S3ClientConfig(region: "us-west-2")
let client = S3Client(config: config)

// WRONG - deprecated class
// let config = try await S3Client.S3ClientConfiguration(region: "us-west-2")

Client Creation

All service clients follow the same pattern: <Service>Client with <Service>Client.<Service>ClientConfig.

Model types (structs/enums used in requests/responses) are namespaced under <Service>ClientTypes:

  • S3ClientTypes.Bucket, S3ClientTypes.Object
  • DynamoDBClientTypes.AttributeValue
  • CloudWatchClientTypes.MetricDatum, CloudWatchClientTypes.Dimension
import AWSS3
import AWSDynamoDB

// Simple - auto-detects region
let s3 = try await S3Client()
let dynamo = try await DynamoDBClient()

// With region
let s3 = try S3Client(region: "us-west-2")

// With config - parameters must be in declaration order
let config = try await S3Client.S3ClientConfig(
    useFIPS: true,
    awsRetryMode: .adaptive,
    maxAttempts: 5,
    region: "us-west-2"
)
let client = S3Client(config: config)

// With custom endpoint and credentials
let config = try await S3Client.S3ClientConfig(
    awsCredentialIdentityResolver: resolver,
    region: "us-west-2",
    endpoint: "https://s3.custom-endpoint.com"
)

Common config parameters (MUST follow declaration order):

  • awsCredentialIdentityResolver - Custom credentials

  • useFIPS - Enable FIPS endpoints

  • useDualStack - Enable dual-stack endpoints

  • awsRetryMode - Retry strategy (.adaptive, .standard, .legacy)

  • maxAttempts - Max retry attempts

  • region - AWS region

  • httpClientEngine - Custom HTTP client (requires HttpClientConfiguration parameter):

    import ClientRuntime
    let httpConfig = HttpClientConfiguration()
    let httpClient = URLSessionHTTPClient(httpClientConfiguration: httpConfig)
    let config = try await S3Client.S3ClientConfig(
        region: "us-east-1",
        httpClientEngine: httpClient
    )
    
  • endpoint - Custom endpoint URL

For service-specific config options or exact parameter order, check Sources/Services/AWS<Service>/Sources/AWS<Service>/<Service>Client.swift in the SDK.

Credential Resolvers

import AWSSDKIdentity
import SmithyIdentity

// Static credentials - pass credential object directly
let creds = AWSCredentialIdentity(accessKey: "AKIA...", secret: "...")
let resolver = StaticAWSCredentialIdentityResolver(creds)

// Assume role - REQUIRES underlying resolver
let underlying = try DefaultAWSCredentialIdentityResolverChain()
let resolver = try STSAssumeRoleAWSCredentialIdentityResolver(
    awsCredentialIdentityResolver: underlying,
    roleArn: "arn:aws:iam::123456789012:role/MyRole",
    sessionName: "session-name"
)

// Use in config
let config = try await S3Client.S3ClientConfig(
    awsCredentialIdentityResolver: resolver,
    region: "us-west-2"
)

Waiters

Import SmithyWaitersAPI. WaiterOptions requires maxWaitTime parameter:

import AWSS3
import SmithyWaitersAPI

let client = try await S3Client()
_ = try await client.waitUntilBucketExists(
    options: WaiterOptions(maxWaitTime: 120.0),
    input: HeadBucketInput(bucket: "my-bucket")
)

Pagination

let input = ListObjectsV2Input(bucket: "my-bucket")
for try await page in client.listObjectsV2Paginated(input: input) {
    for object in page.contents ?? [] {
        print(object.key ?? "")
    }
}

Presigned URLs

let url = try await client.presignedURLForGetObject(
    input: GetObjectInput(bucket: "my-bucket", key: "file.pdf"),
    expiration: 3600
)

Common Operations

// Put object
_ = try await client.putObject(input: PutObjectInput(
    body: .data(data),
    bucket: "bucket",
    key: "key"
))

// Get object
let output = try await client.getObject(input: GetObjectInput(bucket: "bucket", key: "key"))
let data = try await output.body?.readData()

// List buckets
let response = try await client.listBuckets(input: ListBucketsInput())
for bucket in response.buckets ?? [] {
    print(bucket.name ?? "")
}