> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrating Bedrock With Amazon S3 Part 2

> Guide showing a compact Python example that reads text from S3, uses Amazon Bedrock to generate concise summaries, and writes results back to S3 for automation

This lesson walks through a compact, end-to-end Python example that:

* reads a text file from Amazon S3,
* uses Amazon Bedrock to generate a concise summary,
* writes the summary back to S3.

The sample is intentionally small and focused so you can reuse the same pattern in scheduled jobs, event-driven Lambda functions, or batch pipelines.

<Callout icon="lightbulb" color="#1CB2FE">
  Ensure your environment has valid AWS credentials and IAM permissions for S3 and Amazon Bedrock Runtime. Install `boto3` (for example, `pip install boto3`) and set `AWS_REGION` if necessary. See the [Amazon Bedrock overview](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html) for service details.
</Callout>

Overview (high-level)

* Configure constants: region, bucket, S3 keys, and model identifier.
* Initialize boto3 clients for S3 and Bedrock Runtime.
* Read input text from S3.
* Build a concise summarization prompt and call Bedrock's runtime.
* Parse the model response and write the generated summary back to S3.

Quick step summary

| Step | Purpose | Example |
| - | - | - |
| Configure | Set region, bucket, keys, model | `REGION = "us-east-1"` |
| Read from S3 | Retrieve raw source text | `s3.get_object(Bucket=BUCKET_NAME, Key=INPUT_KEY)` |
| Call Bedrock | Send prompt and inferenceConfig | `bedrock.invoke_model(...)` |
| Parse output | Handle common Bedrock response shapes | See examples below |
| Write to S3 | Store summary for downstream use | `s3.put_object(..., Body=summary_text)` |

Complete Python script

* Save as `read_generate_write_s3.py`.
* The script is minimal but includes robust parsing for common Bedrock response shapes.

```python theme={null}
# read_generate_write_s3.py
import boto3
import json
import logging

# -------- Configuration --------
REGION = "us-east-1"
BUCKET_NAME = "kodekloud-intro-bedrock"
INPUT_KEY = "input/customer_reviews.txt"
OUTPUT_KEY = "output/customer_reviews_summary.txt"

# Example model identifier (replace with the model available in your account)
MODEL_ID = "us.anthropic.claude-haiku-4-5-20251001-v1:0"

# -------- Logging --------
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# -------- AWS Clients --------
s3 = boto3.client("s3", region_name=REGION)
bedrock = boto3.client("bedrock-runtime", region_name=REGION)

def read_s3_text(bucket: str, key: str) -> str:
    resp = s3.get_object(Bucket=bucket, Key=key)
    return resp["Body"].read().decode("utf-8")

def write_s3_text(bucket: str, key: str, text: str) -> None:
    s3.put_object(Bucket=bucket, Key=key, Body=text.encode("utf-8"), ContentType="text/plain")

def build_prompt(input_text: str) -> str:
    return f"""
Instruction:
You are summarizing customer feedback for a product team.

Requirements:
- Be concise
- Highlight common themes
- Use bullet points
- Maximum of 5 bullets

Input:
{input_text}
"""

def invoke_bedrock(model_id: str, prompt: str) -> str:
    payload = {"input": prompt}
    response = bedrock.invoke_model(
        modelId=model_id,
        contentType="application/json",
        accept="application/json",
        body=json.dumps(payload).encode("utf-8"),
        inferenceConfig={
            "maxTokensToSample": 300,
            "temperature": 0.2
        }
    )
    return response["body"].read().decode("utf-8")

def parse_bedrock_response(resp_body: str) -> str:
    """
    Attempt to handle several common Bedrock JSON shapes:
    - `{"outputs": [{"content":[{"text":"..."}]}]}`
    - `{"output": {"message": {"content": [{"text":"..."}]}}}`
    - `{"generated_text": "..."}` or `{"text": "..."}`

    Falls back to returning the raw response body if parsing fails.
    """
    try:
        obj = json.loads(resp_body)
        # outputs -> content -> text
        if isinstance(obj, dict):
            if "outputs" in obj and isinstance(obj["outputs"], list):
                parts = []
                for out in obj["outputs"]:
                    if isinstance(out, dict) and "content" in out and isinstance(out["content"], list):
                        for c in out["content"]:
                            if isinstance(c, dict) and "text" in c:
                                parts.append(c["text"])
                if parts:
                    return "".join(parts)
            # output -> message -> content -> text
            if "output" in obj and isinstance(obj["output"], dict):
                output = obj["output"]
                if "message" in output and isinstance(output["message"], dict) and "content" in output["message"]:
                    parts = []
                    for c in output["message"]["content"]:
                        if isinstance(c, dict) and "text" in c:
                            parts.append(c["text"])
                    if parts:
                        return "".join(parts)
            # simpler fields
            if "generated_text" in obj:
                return obj["generated_text"]
            if "text" in obj:
                return obj["text"]
        # If no known pattern matched, return the raw response
        return resp_body
    except Exception:
        # On parse error, return raw response body
        return resp_body

def main():
    logger.info("Reading input file from S3...")
    input_text = read_s3_text(BUCKET_NAME, INPUT_KEY)
    logger.info("Input read (truncated): %s", input_text[:200])

    prompt = build_prompt(input_text)

    logger.info("Invoking Bedrock model...")
    raw_resp = invoke_bedrock(MODEL_ID, prompt)

    logger.info("Parsing model response...")
    summary = parse_bedrock_response(raw_resp)

    logger.info("Writing summary back to S3...")
    write_s3_text(BUCKET_NAME, OUTPUT_KEY, summary)

    logger.info("Summary written to s3://%s/%s", BUCKET_NAME, OUTPUT_KEY)

if __name__ == "__main__":
    main()
```

How the response parsing maps to common Bedrock outputs

| Response Shape | What it looks like | How the script handles it |
| - | - | - |
| Outputs array | `{"outputs":[{"content":[{"text":"..."}]}]}` | Script concatenates `content[*].text` values. |
| Output message | `{"output":{"message":{"content":[{"text":"..."}]}}}` | Script extracts `message.content[*].text`. |
| Simple text fields | `{"generated_text": "..."} or {"text":"..."}` | Script returns `generated_text` or `text`. |
| Unknown / non-JSON | Raw string | Falls back to using the raw response body. |

Terminal example (trimmed)

```bash theme={null}
$ python3 read_generate_write_s3.py
INFO:__main__:Reading input file from S3...
INFO:__main__:Input read (truncated): 1. Absolutely love this product. Setup took less than five minutes and it works flawlessly.
...
INFO:__main__:Invoking Bedrock model...
INFO:__main__:Parsing model response...
INFO:__main__:Writing summary back to S3...
INFO:__main__:Summary written to s3://kodekloud-intro-bedrock/output/customer_reviews_summary.txt
```

Post-run: view the generated summary

* Use the S3 console: [https://s3.console.aws.amazon.com/s3/home](https://s3.console.aws.amazon.com/s3/home)
* Or the AWS CLI: `aws s3 cp s3://kodekloud-intro-bedrock/output/customer_reviews_summary.txt -`

A typical generated summary might look like:

```text theme={null}
- **Setup & Performance**: Quick setup and reliable functionality when working properly.
- **Quality Control & Shipping**: Multiple reports of defective units and damaged packaging upon delivery.
- **Customer Support**: Inconsistent experience — some customers received prompt replacements while others received canned responses.
- **Documentation & Battery Life**: Instructions unclear and occasional complaints about battery life.
- **Value**: Generally perceived as good value for the price.
```

Best practices and why this pattern is useful

* Scales from single-file processing to batch/stream workflows.
* Use S3 as a persistent, cost-effective storage layer for raw inputs and processed outputs.
* Trigger options: scheduled jobs, S3 events + Lambda, containerized consumers, or stream processors.
* Tune prompt engineering and model parameters (`temperature`, `maxTokensToSample`) to adjust style and length.

Common pitfalls and troubleshooting

<Callout icon="warning" color="#FF6B6B">
  Check your IAM policies: you need permissions to read/write the S3 objects and permission to call Bedrock Runtime APIs. If you see access denied errors, verify the role or credentials used by your environment (CLI, EC2, Lambda, or container).
</Callout>

Additional notes and references

* If you need finer-grained control over streaming outputs or different Bedrock integrations, some SDKs or model adapters may expose other method names (for example, `converse`) or different response envelopes—adapt the parsing logic accordingly.
* Useful links:
  * [Amazon Bedrock user guide](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html)
  * [boto3 S3 client](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html)
  * [boto3 clients: bedrock-runtime](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock-runtime.html) (if available for your SDK version)

Why this integration matters

* Programmatic summarization and extraction enable teams to unlock insights from existing text data without manual aggregation.
* The pattern is adaptable to many text-processing tasks (classification, extraction, QA) and integrates naturally with analytics or downstream automation.

Key takeaway:

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/4OlDw81IoiRnJTCQ/images/Introduction-to-Amazon-Bedrock/Integrating-Amazon-Bedrock-With-Other-AWS-Services/Integrating-Bedrock-With-Amazon-S3-Part-2/ai-applied-to-s3-data.jpg?fit=max&auto=format&n=4OlDw81IoiRnJTCQ&q=85&s=e8fdf465e9114034c1b0e941a1c6e57e" alt="A slide titled &#x22;Key Takeaway&#x22; with a blue left panel and a numbered badge. The takeaway reads: &#x22;AI becomes valuable when applied directly to data stored in systems such as S3.&#x22;" width="1920" height="1080" data-path="images/Introduction-to-Amazon-Bedrock/Integrating-Amazon-Bedrock-With-Other-AWS-Services/Integrating-Bedrock-With-Amazon-S3-Part-2/ai-applied-to-s3-data.jpg" />
</Frame>

S3 provides a simple, programmatic storage layer that, when combined with Bedrock, lets you unlock the insights hidden in your existing data.

Next steps

* Run the sample script against your own bucket and input files.
* Experiment with different prompts, model IDs, and inferenceConfig parameters.
* Integrate the pattern into a production flow: S3 events + Lambda, step functions, or batch jobs.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/4OlDw81IoiRnJTCQ/images/Introduction-to-Amazon-Bedrock/Integrating-Amazon-Bedrock-With-Other-AWS-Services/Integrating-Bedrock-With-Amazon-S3-Part-2/bedrock-amazon-s3-lab-presentation.jpg?fit=max&auto=format&n=4OlDw81IoiRnJTCQ&q=85&s=1ba753cfc27cbb9cf8e412ae31e77134" alt="A presentation slide titled &#x22;What's Next? Using Bedrock with Amazon S3 Lab&#x22; with a teal AI/circuit brain icon on a dark curved background. The slide also shows a small &#x22;© Copyright KodeKloud&#x22; in the corner." width="1920" height="1080" data-path="images/Introduction-to-Amazon-Bedrock/Integrating-Amazon-Bedrock-With-Other-AWS-Services/Integrating-Bedrock-With-Amazon-S3-Part-2/bedrock-amazon-s3-lab-presentation.jpg" />
</Frame>

Build on this basic pattern to create production-ready automation and scalable text processing pipelines with Amazon Bedrock and Amazon S3.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/introduction-to-amazon-bedrock/module/6a77d10e-3172-4684-96bf-8e168372fae5/lesson/8b76c85b-6c2f-45c2-9e50-096ed844b92f" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/introduction-to-amazon-bedrock/module/6a77d10e-3172-4684-96bf-8e168372fae5/lesson/5fa5517a-25bc-4ff6-bc11-60b7a33cf198" />
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.