Agentic AI in Practice
From Knowledge Retrieval to an Autonomous Agent with FSxN

Recap & Starting Point
Part 1 of this series showed why agentic AI confronts public cloud infrastructure with three central challenges: identity & governance for non-human identities, real-time data pipelines, and scalable model serving. This second part gets concrete: we build on the existing enterprise knowledge base architecture with Amazon Bedrock and FSxN and extend it with an agentic action layer.
The earlier knowledge base article describes a classic RAG system: the user asks a question, the system searches the FSxN-backed knowledge base via S3 Access Points, and returns an answer. That works well for simple queries — but it reaches its limits as soon as multi-step tasks requiring independent decisions come into play.
From RAG System to Agent — What Changes
A pure RAG system follows a fixed pattern: retrieval, then answer. An agent, by contrast, can decide for itself whether and how often to query the knowledge base, whether it considers the result sufficient or needs to follow up specifically, and whether a further action is required — such as updating a ticket or triggering a downstream process.
Technically, this capability is realized through Action Groups in Amazon Bedrock Agents: the agent gets access to defined functions (tools) that it calls independently as part of its planning. In our case, one of these functions is the existing FSxN-backed knowledge base — complemented by a Lambda function that acts as a broker between the agent and the data layer, enforcing the access controls already established there.
Extended Reference Architecture
The following architecture builds directly on the familiar knowledge base structure and adds two new layers: the Bedrock Agent with Action Group as the orchestration layer, and an IAM role that anchors the agent as an independent, restricted identity within the system.
Additionally, a FlexClone sandbox appears in the architecture: before a new version of the agent or Lambda handler goes into production, FlexClone can create an isolated copy of the knowledge base in seconds, against which test runs take place — with no risk to production data.
Three Concrete Building Blocks
Example 1: IAM Role for the Agent Identity
The agent needs its own tightly scoped IAM role. The following policy grants access exclusively to the relevant S3 Access Point and model invocation — nothing more:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowKnowledgeBaseAccessPoint",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:us-east-1:111122223333:accesspoint/agent-kb-ap",
"arn:aws:s3:us-east-1:111122223333:accesspoint/agent-kb-ap/object/*"
]
},
{
"Sid": "AllowBedrockAgentRuntime",
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:Retrieve"
],
"Resource": "arn:aws:bedrock:us-east-1:111122223333:knowledge-base/KB123ABC"
},
{
"Sid": "AllowLambdaInvocation",
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:111122223333:function:agent-kb-handler"
}
]
}
What matters most here is the combination of resource-specific ARNs instead of wildcards: the agent can access only the access point and knowledge base intended for it — exactly the least-privilege principle described as a governance requirement in Part 1.
Example 2: Lambda Handler with ACL-Aware Filtering
The agent’s Action Group calls a Lambda function that forwards the request to the knowledge base while also taking into account the permissions of the original requester — not just those of the agent itself. This preserves the multi-layer access control already established in the knowledge base article, even in the agentic context:
import boto3
bedrock_agent_runtime = boto3.client("bedrock-agent-runtime")
def lambda_handler(event, context):
query = event["inputText"]
requester_group = event["sessionAttributes"].get("userGroup")
response = bedrock_agent_runtime.retrieve(
knowledgeBaseId="KB123ABC",
retrievalQuery={"text": query},
retrievalConfiguration={
"vectorSearchConfiguration": {
"numberOfResults": 5,
"filter": {
"equals": {
"key": "acl_group",
"value": requester_group
}
}
}
},
)
results = response.get("retrievalResults", [])
context_text = "n".join(r["content"]["text"] for r in results)
return {
"messageVersion": "1.0",
"response": {
"actionResponse": {
"actionResponseBody": {
"TEXT": {"body": context_text}
}
}
},
}
The key point is the acl_group metadata filter: it ensures that the agent, acting on behalf of the user, only accesses documents authorized for that user’s permission group — the metadata filtering from the original knowledge base article is carried over one-to-one into the agent architecture, rather than being bypassed by the agent’s autonomy.
Example 3: FlexClone Automation for Agent Testing
Before every test run of a new agent or handler version, a FlexClone snapshot of production data can be created automatically via boto3. The following script shows the core workflow for an FSxN volume:
import boto3
import time
fsx = boto3.client("fsx")
def create_test_clone(source_volume_id: str, clone_name: str) -> str:
response = fsx.create_volume(
VolumeType="ONTAP",
Name=clone_name,
OntapConfiguration={
"StorageVirtualMachineId": "svm-0123456789abcdef0",
"JunctionPath": f"/{clone_name}",
"SizeInMegabytes": 102400,
"OntapVolumeType": "RW",
"SnapshotPolicy": "none",
"CopyTagsToBackups": False,
# FlexClone: the new volume references the source volume efficiently
"ClonedVolumeSource": {
"VolumeId": source_volume_id,
"SnapshotId": "latest"
},
},
)
volume_id = response["Volume"]["VolumeId"]
while True:
status = fsx.describe_volumes(VolumeIds=[volume_id])
lifecycle = status["Volumes"][0]["Lifecycle"]
if lifecycle == "AVAILABLE":
break
time.sleep(5)
return volume_id
# Example: create an isolated test copy for the next CI run
test_volume = create_test_clone(
source_volume_id="fsvol-0abc123def456789",
clone_name="agent-test-run-482",
)
print(f"Sandbox volume ready: {test_volume}")
This script can be hooked directly into a CI/CD pipeline: before every automated test run, a fresh, isolated copy of production data is created in seconds rather than minutes or hours — without consuming the storage footprint of a full copy operation.
Governance in Practice
The three examples map directly back to the requirements described in Part 1:
| Requirement from Part 1 | Concrete implementation in Part 2 |
|---|---|
| Identity & governance for non-human identities | Least-privilege IAM role (Example 1); Lambda handler enforces ACL filtering per request |
| Real-time data pipelines & vector databases | Bedrock Knowledge Base + S3 Access Points as the existing RAG pipeline, now driven agentically |
| Scalable model-serving infrastructure | Action Group architecture separates orchestration (agent) from retrieval (knowledge base) for independent scaling |
The key difference from Part 1: governance is no longer an abstract principle here, but concretely traceable in policy documents, filtering logic, and automation scripts.
Pitfalls & Lessons Learned
In practice, three recurring challenges emerge. First: latency from nested tool calls. Every additional step the agent introduces adds to the overall response time — for interactive use cases, it’s worth deliberately limiting the number of Action Group calls per request.
Second: snapshot freshness versus test consistency. If the FlexClone is refreshed too rarely, tests run against stale data; if refreshed too often, compute and coordination overhead rises. A daily refresh cycle has proven to be a good compromise in most scenarios.
Third: test automation moves from nice-to-have to mandatory. Since the agent acts autonomously, its behavior can no longer be safeguarded through manual spot checks alone — automated test runs against the FlexClone sandbox are the only practical way to reliably catch regressions before they reach production.
Conclusion & Outlook
Extending the existing knowledge base architecture with an agentic action layer shows that the three requirements from Part 1 don’t have to remain abstract concepts: least-privilege IAM roles, ACL-aware retrieval logic, and FlexClone-backed test automation can be implemented in production with comparatively little additional code.
An obvious next step for a potential third part would be observability: how do you keep track of which decisions an agent makes in production, which tools it calls and how often, and where costs or latency start to run away? That would round out the series — from architecture, through implementation, to operations.

Comments are closed