# Buggy code
def get_boto_client(
    resource: str, credentials: dict = None, use_session: bool = False, **kwargs: Any
) -> "boto3.client":
    """
    Utility function for loading boto3 client objects from a given set of credentials.

    Args:
        - resource (str): the name of the resource to retrieve a client for
        - credentials (dict, optional): a dictionary of AWS credentials used to initialize the Client; if
            not provided, will attempt to load the Client using ambient environment settings
        - use_session (bool, optional): a boolean specifying whether to load this client using a session or not;
            defaults to `False`
        - **kwargs (Any, optional): additional keyword arguments to pass to boto3

    Returns:
        - Client: an initialized and authenticated boto3 Client
    """
    aws_access_key = None
    aws_secret_access_key = None
    aws_session_token = None

    if credentials:
        aws_access_key = credentials["ACCESS_KEY"]
        aws_secret_access_key = credentials["SECRET_ACCESS_KEY"]
        aws_session_token = credentials.get("SESSION_TOKEN")
    else:
        ctx_credentials = prefect.context.get("secrets", {}).get("AWS_CREDENTIALS", {})
        aws_access_key = ctx_credentials.get("ACCESS_KEY")
        aws_secret_access_key = ctx_credentials.get("SECRET_ACCESS_KEY")
        aws_session_token = ctx_credentials.get("SESSION_TOKEN")

    if use_session:
        # see https://boto3.amazonaws.com/v1/documentation/api/latest/guide/resources.html?#multithreading-multiprocessing
        session = boto3.session.Session()
        return session.client(
            resource,
            aws_access_key_id=aws_access_key,
            aws_secret_access_key=aws_secret_access_key,
            aws_session_token=aws_session_token,
            **kwargs,
        )
    else:
        return boto3.client(
            resource,
            aws_access_key_id=aws_access_key,
            aws_secret_access_key=aws_secret_access_key,
            aws_session_token=aws_session_token,
            **kwargs,
        )


# Traceback (TypeError)
prefect-agent_1      | [2020-06-09 07:59:36] DEBUG - prefect.S3Result | Starting to upload result to 2020/6/9/5a96e8ef-70d1-4d47-a495-15b0afa99169.prefect_result...
prefect-agent_1      | [2020-06-09 07:59:36] ERROR - prefect.CloudTaskRunner | Unexpected error: TypeError("client() got multiple values for keyword argument 'aws_access_key_id'")
prefect-agent_1      | Traceback (most recent call last):
prefect-agent_1      |   File "/usr/local/lib/python3.7/site-packages/prefect/engine/runner.py", line 48, in inner
prefect-agent_1      |     new_state = method(self, state, *args, **kwargs)
prefect-agent_1      |   File "/usr/local/lib/python3.7/site-packages/prefect/engine/task_runner.py", line 986, in get_task_run_state
prefect-agent_1      |     result = self.result.write(value, filename="output", **prefect.context)
prefect-agent_1      |   File "/usr/local/lib/python3.7/site-packages/prefect/engine/results/s3_result.py", line 103, in write
prefect-agent_1      |     self.client.upload_fileobj(stream, Bucket=self.bucket, Key=new.location)
prefect-agent_1      |   File "/usr/local/lib/python3.7/site-packages/prefect/engine/results/s3_result.py", line 60, in client
prefect-agent_1      |     self.initialize_client()
prefect-agent_1      |   File "/usr/local/lib/python3.7/site-packages/prefect/engine/results/s3_result.py", line 49, in initialize_client
prefect-agent_1      |     "s3", credentials=None, use_session=True, **self.boto3_kwargs
prefect-agent_1      |   File "/usr/local/lib/python3.7/site-packages/prefect/utilities/aws.py", line 49, in get_boto_client
prefect-agent_1      |     **kwargs
prefect-agent_1      | TypeError: client() got multiple values for keyword argument 'aws_access_key_id'

# Fixed code
def get_boto_client(
    resource: str, credentials: dict = None, use_session: bool = False, **kwargs: Any
) -> "boto3.client":
    """
    Utility function for loading boto3 client objects from a given set of credentials.

    Args:
        - resource (str): the name of the resource to retrieve a client for
        - credentials (dict, optional): a dictionary of AWS credentials used to initialize the Client; if
            not provided, will attempt to load the Client using ambient environment settings
        - use_session (bool, optional): a boolean specifying whether to load this client using a session or not;
            defaults to `False`
        - **kwargs (Any, optional): additional keyword arguments to pass to boto3

    Returns:
        - Client: an initialized and authenticated boto3 Client
    """
    aws_access_key = None
    aws_secret_access_key = None
    aws_session_token = None

    if credentials:
        aws_access_key = credentials["ACCESS_KEY"]
        aws_secret_access_key = credentials["SECRET_ACCESS_KEY"]
        aws_session_token = credentials.get("SESSION_TOKEN")
    else:
        ctx_credentials = prefect.context.get("secrets", {}).get("AWS_CREDENTIALS", {})
        aws_access_key = ctx_credentials.get("ACCESS_KEY")
        aws_secret_access_key = ctx_credentials.get("SECRET_ACCESS_KEY")
        aws_session_token = ctx_credentials.get("SESSION_TOKEN")

    if use_session:
        # see https://boto3.amazonaws.com/v1/documentation/api/latest/guide/resources.html?#multithreading-multiprocessing
        session = boto3.session.Session()
        return session.client(
            resource,
            aws_access_key_id=aws_access_key or kwargs.pop("aws_access_key_id", None),
            aws_secret_access_key=aws_secret_access_key
            or kwargs.pop("aws_secret_access_key", None),
            aws_session_token=aws_session_token
            or kwargs.pop("aws_session_token", None),
            **kwargs,
        )
    else:
        return boto3.client(
            resource,
            aws_access_key_id=aws_access_key or kwargs.pop("aws_access_key_id", None),
            aws_secret_access_key=aws_secret_access_key
            or kwargs.pop("aws_secret_access_key", None),
            aws_session_token=aws_session_token
            or kwargs.pop("aws_session_token", None),
            **kwargs,
        )