
Amazon S3 as a living data layer for your AWS Transform agent
Give your AWS Transform agent direct S3 access to read config files, write structured output, and trigger downstream workflows via EventBridge. Three patterns, one integration surface.
Your AWS Transform agent runs in your account, with your IAM role, and your credentials. That means it can talk to Amazon S3 the same way any other workload in your account does. No special SDK. No connector. Just
boto3.client("s3") and whatever permissions you put on the role.This article walks through three patterns for using S3 as the integration surface between your agent and the rest of your AWS environment: input (other systems feed the agent), output (the agent writes for downstream consumers), and events (S3 triggers actions when the agent writes).
Prerequisites
- An AWS account with AWS Transform configured
- An agent deployed to AWS Transform (the Agent Builder Toolkit in Kiro is the fastest path)
- Basic IAM knowledge (inline policies, role trust)
- An S3 bucket in the same account (or cross-account with appropriate trust)
Why go beyond the Artifacts Store
AWS Transform gives you an Artifacts Store out of the box. You upload files through the webapp, the agent reads and writes during a job. You can bring your own S3 bucket as the backing store.
That covers the job lifecycle. But your agent exists inside a broader architecture. It might need to:
- Read a config file that your ops team updates independently of any job
- Write structured output to a location a dashboard already consumes
- Trigger a notification pipeline the moment it finishes work
Direct S3 access makes your agent a first-class citizen of your AWS account, not just a participant in the Transform workflow.
How your agent gets S3 access
The credential model:
- Your agent runs on AWS Transform in your AWS account.
- AWS Transform runs your agent via Amazon Bedrock AgentCore , which assumes your agent's execution role and injects credentials into the runtime environment. If you deployed with the Agent Builder Toolkit in Kiro, this role is named
AgentCoreExecutionRoleby default. - Your agent code calls
boto3.client("s3"). The standard credential chain picks up the injected credentials automatically. - Whatever permissions are on that role, your agent has.
No credential fetching code. No token refresh logic. No role assumption calls. AWS Transform handles credential rotation for the duration of the job.
The recommended role template does not include S3 access by default. You add it.
Grant your agent S3 access
Attach a scoped inline policy to your agent's execution role (substitute your actual role name if different):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
aws iam put-role-policy \
--role-name AgentCoreExecutionRole \
--policy-name S3DataLayerAccess \
--policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::my-agent-data-bucket",
"arn:aws:s3:::my-agent-data-bucket/*"
]
}]
}'Scope it to exactly the bucket or prefix your agent needs. Do not use
s3:* on *. The IAM security best practices apply here the same as anywhere else.Pattern 1: S3 as input
Any process that can write to S3 can feed your agent. Your ops team, a CI/CD pipeline, another service. The agent reads the latest version at job start without any code change or redeployment.
Example: A mapping table that translates legacy system codes to modern equivalents. Your domain team maintains it. The agent consumes it.
1
2
3
4
5
6
7
8
9
10
import json
import boto3
from strands import tool
def load_mapping(bucket: str) -> dict:
"""Load the current mapping table from S3."""
s3 = boto3.client("s3")
response = s3.get_object(Bucket=bucket, Key="config/mapping.json")
return json.loads(response["Body"].read())The
@tool decorator from Strands Agents SDK exposes this function to the agent's orchestrator. The agent decides when to call it based on context.Pattern 2: S3 as output
Your agent writes structured output to an agreed-upon S3 location. Downstream systems consume it. The agent doesn't need to know about those systems, and they don't need to know about the agent's internals.
Example: The agent writes a migration assessment as JSON. A separate AWS Lambda function picks it up and updates a QuickSight dashboard. The agent never touches QuickSight.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import json
import boto3
from strands import tool
def publish_assessment(bucket: str, job_id: str, assessment: dict) -> str:
"""Publish assessment results for downstream consumption."""
s3 = boto3.client("s3")
key = f"assessments/{job_id}/result.json"
s3.put_object(
Bucket=bucket,
Key=key,
Body=json.dumps(assessment, indent=2).encode("utf-8"),
ContentType="application/json"
)
return f"s3://{bucket}/{key}"The contract between agent and consumer is the S3 prefix and the JSON schema. Nothing more.
Pattern 3: S3 events
When the agent writes to S3, Amazon EventBridge can fire an event. Other systems react. The agent doesn't call them. The event does.
Example: The agent writes
result.json. EventBridge fires. A Lambda sends a Slack notification.Enable EventBridge notifications on your bucket:
1
2
3
aws s3api put-bucket-notification-configuration \
--bucket my-agent-data-bucket \
--notification-configuration '{"EventBridgeConfiguration":{}}'Create an EventBridge rule that matches PutObject events on the assessments prefix:
1
2
3
4
5
6
7
8
9
10
aws events put-rule \
--name agent-output-written \
--event-pattern '{
"source": ["aws.s3"],
"detail-type": ["Object Created"],
"detail": {
"bucket": { "name": ["my-agent-data-bucket"] },
"object": { "key": [{ "prefix": "assessments/" }] }
}
}'Lambda target that posts to Slack:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import json
import urllib.request
SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/..."
def handler(event, context):
bucket = event["detail"]["bucket"]["name"]
key = event["detail"]["object"]["key"]
message = f"Agent completed: s3://{bucket}/{key}"
payload = json.dumps({"text": message}).encode("utf-8")
req = urllib.request.Request(
SLACK_WEBHOOK_URL,
data=payload,
headers={"Content-Type": "application/json"}
)
urllib.request.urlopen(req)
return {"statusCode": 200}The agent wrote a file. The rest happened without the agent knowing or caring.
Putting it together

Figure 1. Amazon S3 as the integration surface between your agent and the rest of your AWS account.
A worked example combining all three patterns:
- Before the job: Your ops team uploads
mapping.jsontos3://my-bucket/config/. The agent reads it at job start. - During the job: The agent processes customer workloads using the mapping data.
- After the job: The agent writes
assessment.jsontos3://my-bucket/assessments/{job-id}/. - Automatically: EventBridge catches the PutObject event. Lambda sends a Slack message. Downstream workflows pick up the output.
The agent stays focused on its domain logic. S3 is the seam between it and everything else.
Get started
- Create your S3 bucket (standard, nothing AWS Transform-specific about it)
- Add a scoped IAM policy to
AgentCoreExecutionRolegranting access to that bucket - Deploy your agent. If already deployed, the updated IAM policy takes effect on the next job invocation.
- Use
boto3.client("s3")in your agent code. It just works.
Conclusion
S3 gives your agent a way to participate in your broader AWS architecture without coupling to downstream systems. Three patterns, one integration surface:
- Input: anything that writes to S3 can feed your agent
- Output: anything that reads from S3 can consume your agent's work
- Events: anything that listens to EventBridge can react when your agent writes
These are intentionally simple examples. Your agent doesn't need to know who's reading its output or who's updating its config. That's the point. S3 is the data layer. The agent stays focused on what it's good at.
The same structure scales: swap the mapping file for a feature flag system, the assessment JSON for a multi-account inventory, the Slack notification for a Step Functions workflow that another team owns. The patterns don't change. Your agent writes to S3, and the rest of your architecture reacts.
This information is accurate as of July 2026. AWS Transform and Amazon Bedrock AgentCore are actively evolving services. Consult the reference documents linked above for the most current security guidance.
Building agents on Transform? I'd like to hear about it. Find me on LinkedIn .
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article