Skip to main content

AWS AI Services

Building AI Agents with Amazon Bedrock: From Concept to Production

Complete guide to building autonomous AI agents using Amazon Bedrock Agents for Australian businesses, covering agent design, action groups, knowledge bases, and orchestration patterns.

CloudPoint

CloudPoint Team

AI agents represent the next evolution in generative AI applications. Unlike simple chatbots that respond to queries, agents can plan multi-step tasks, use tools, access knowledge bases, and take actions on your behalf. Amazon Bedrock Agents provides a fully managed service for building autonomous AI agents without managing infrastructure. For Australian businesses, this enables sophisticated automation while maintaining security and compliance.

What are AI Agents?

AI agents are autonomous systems that can:

  • Understand complex, multi-step requests
  • Plan sequences of actions to achieve goals
  • Use external tools and APIs
  • Access knowledge bases for information
  • Make decisions based on context
  • Execute tasks with minimal human intervention

Traditional Chatbot vs AI Agent

Traditional Chatbot:

User: "Book a meeting with the sales team next Tuesday"
Bot: "I can help with that. Please visit calendar.company.com to book a meeting."

AI Agent:

User: "Book a meeting with the sales team next Tuesday"
Agent:
1. Checks calendar availability for sales team
2. Finds available slot on Tuesday at 2pm
3. Creates meeting invite
4. Sends calendar invitations
5. Confirms: "Meeting booked for Tuesday, Nov 28 at 2:00 PM AEDT with Sales Team"

Agent Components

Foundation Model: The AI brain that understands requests and plans actions.

Action Groups: Capabilities the agent can perform (APIs, Lambda functions).

Knowledge Bases: Information repositories the agent can query.

Orchestration: The logic that coordinates actions to achieve goals.

Guardrails: Safety controls to prevent harmful outputs.

Agent Architecture

Basic Agent Structure

import boto3
import json

class BedrockAgent:
    def __init__(self, agent_id: str, agent_alias_id: str):
        self.bedrock_agent_runtime = boto3.client(
            'bedrock-agent-runtime',
            region_name='ap-southeast-2'
        )
        self.agent_id = agent_id
        self.agent_alias_id = agent_alias_id

    def invoke(self, prompt: str, session_id: str = None) -> dict:
        """Invoke Bedrock agent with a prompt."""

        response = self.bedrock_agent_runtime.invoke_agent(
            agentId=self.agent_id,
            agentAliasId=self.agent_alias_id,
            sessionId=session_id or self._generate_session_id(),
            inputText=prompt
        )

        # Stream response
        completion = ""
        for event in response['completion']:
            if 'chunk' in event:
                chunk = event['chunk']
                completion += chunk['bytes'].decode('utf-8')

        return {
            'completion': completion,
            'session_id': response['sessionId']
        }

    def _generate_session_id(self) -> str:
        """Generate unique session ID."""
        from uuid import uuid4
        return str(uuid4())

Agent Workflow

User Input

Foundation Model (Understands intent)

Planning (Breaks down into steps)

Action Selection (Choose appropriate tool)

Action Execution (Call API/Lambda)

Response Processing (Interpret results)

Next Action or Final Response

Creating Your First Agent

1. Define Agent Purpose

Example: Australian Business Assistant:

agent_instruction = """You are an Australian business assistant that helps with:
1. Checking company information via ASIC lookup
2. Validating ABN (Australian Business Numbers)
3. Calculating GST and business expenses
4. Providing business registration guidance
5. Australian business compliance reminders

Always use Australian terminology, date formats (DD/MM/YYYY), and currency (AUD).
Be professional and helpful. For legal or financial advice, recommend consulting appropriate professionals."""

2. Set Up Action Groups

Action groups define what the agent can do:

import boto3

class AgentActionGroups:
    def __init__(self):
        self.bedrock_agent = boto3.client('bedrock-agent', region_name='ap-southeast-2')

    def create_action_group(
        self,
        agent_id: str,
        action_group_name: str,
        lambda_arn: str,
        api_schema: dict
    ) -> str:
        """Create action group for agent."""

        response = self.bedrock_agent.create_agent_action_group(
            agentId=agent_id,
            agentVersion='DRAFT',
            actionGroupName=action_group_name,
            actionGroupExecutor={
                'lambda': lambda_arn
            },
            apiSchema={
                'payload': json.dumps(api_schema)
            },
            description=f'Action group for {action_group_name}'
        )

        return response['agentActionGroup']['actionGroupId']

# Define API schema for ABN validation
abn_validation_schema = {
    "openapi": "3.0.0",
    "info": {
        "title": "ABN Validation API",
        "version": "1.0.0",
        "description": "Validate Australian Business Numbers"
    },
    "paths": {
        "/validate-abn": {
            "post": {
                "summary": "Validate ABN",
                "description": "Validates an Australian Business Number",
                "requestBody": {
                    "required": True,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "abn": {
                                        "type": "string",
                                        "description": "11-digit Australian Business Number"
                                    }
                                },
                                "required": ["abn"]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Validation result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "valid": {"type": "boolean"},
                                        "abn": {"type": "string"},
                                        "entity_name": {"type": "string"},
                                        "status": {"type": "string"}
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/calculate-gst": {
            "post": {
                "summary": "Calculate GST",
                "description": "Calculate GST for Australian prices",
                "requestBody": {
                    "required": True,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "amount": {
                                        "type": "number",
                                        "description": "Amount in AUD"
                                    },
                                    "gst_inclusive": {
                                        "type": "boolean",
                                        "description": "Whether amount includes GST"
                                    }
                                },
                                "required": ["amount"]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "GST calculation",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "base_amount": {"type": "number"},
                                        "gst_amount": {"type": "number"},
                                        "total_amount": {"type": "number"}
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

3. Create Lambda Functions

Implement actions as Lambda functions:

# lambda_function.py
import json

def validate_abn(abn: str) -> dict:
    """Validate Australian Business Number using weighted checksum."""

    # Remove spaces and hyphens
    clean_abn = abn.replace(' ', '').replace('-', '')

    # Validate format
    if len(clean_abn) != 11 or not clean_abn.isdigit():
        return {
            'valid': False,
            'abn': abn,
            'error': 'ABN must be 11 digits'
        }

    # Apply weighting
    weights = [10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
    digits = [int(d) for d in clean_abn]

    # Subtract 1 from first digit
    digits[0] -= 1

    # Calculate weighted sum
    total = sum(d * w for d, w in zip(digits, weights))

    # Check if divisible by 89
    is_valid = (total % 89) == 0

    # In production, query ABR (Australian Business Register) API
    # for entity details
    entity_name = "Example Pty Ltd" if is_valid else None
    status = "Active" if is_valid else "Invalid"

    return {
        'valid': is_valid,
        'abn': clean_abn,
        'entity_name': entity_name,
        'status': status
    }

def calculate_gst(amount: float, gst_inclusive: bool = False) -> dict:
    """Calculate GST for Australian prices."""

    gst_rate = 0.10  # 10% GST

    if gst_inclusive:
        # Amount includes GST, extract it
        base_amount = amount / (1 + gst_rate)
        gst_amount = amount - base_amount
        total_amount = amount
    else:
        # Amount excludes GST, add it
        base_amount = amount
        gst_amount = amount * gst_rate
        total_amount = amount + gst_amount

    return {
        'base_amount': round(base_amount, 2),
        'gst_amount': round(gst_amount, 2),
        'total_amount': round(total_amount, 2),
        'gst_rate': gst_rate
    }

def lambda_handler(event, context):
    """AWS Lambda handler for Bedrock Agent actions."""

    # Extract action and parameters
    action = event['actionGroup']
    api_path = event['apiPath']
    parameters = event.get('parameters', [])

    # Convert parameters to dict
    params = {p['name']: p['value'] for p in parameters}

    # Route to appropriate function
    if api_path == '/validate-abn':
        result = validate_abn(params['abn'])
    elif api_path == '/calculate-gst':
        result = calculate_gst(
            float(params['amount']),
            params.get('gst_inclusive', 'false').lower() == 'true'
        )
    else:
        return {
            'statusCode': 400,
            'body': json.dumps({'error': 'Unknown action'})
        }

    # Return response in Bedrock Agent format
    return {
        'messageVersion': '1.0',
        'response': {
            'actionGroup': action,
            'apiPath': api_path,
            'httpMethod': 'POST',
            'httpStatusCode': 200,
            'responseBody': {
                'application/json': {
                    'body': json.dumps(result)
                }
            }
        }
    }

4. Create Knowledge Base

Add knowledge sources for the agent:

class KnowledgeBaseManager:
    def __init__(self):
        self.bedrock_agent = boto3.client('bedrock-agent', region_name='ap-southeast-2')

    def create_knowledge_base(
        self,
        name: str,
        description: str,
        embeddings_model: str = 'amazon.titan-embed-text-v1'
    ) -> str:
        """Create knowledge base for agent."""

        response = self.bedrock_agent.create_knowledge_base(
            name=name,
            description=description,
            roleArn=self._get_kb_role_arn(),
            knowledgeBaseConfiguration={
                'type': 'VECTOR',
                'vectorKnowledgeBaseConfiguration': {
                    'embeddingModelArn': f'arn:aws:bedrock:ap-southeast-2::foundation-model/{embeddings_model}'
                }
            },
            storageConfiguration={
                'type': 'OPENSEARCH_SERVERLESS',
                'opensearchServerlessConfiguration': {
                    'collectionArn': self._get_opensearch_collection_arn(),
                    'vectorIndexName': f'{name}-index',
                    'fieldMapping': {
                        'vectorField': 'embedding',
                        'textField': 'text',
                        'metadataField': 'metadata'
                    }
                }
            }
        )

        return response['knowledgeBase']['knowledgeBaseId']

    def add_data_source(
        self,
        knowledge_base_id: str,
        s3_bucket: str,
        s3_prefix: str
    ) -> str:
        """Add S3 data source to knowledge base."""

        response = self.bedrock_agent.create_data_source(
            knowledgeBaseId=knowledge_base_id,
            name='australian-business-docs',
            dataSourceConfiguration={
                'type': 'S3',
                's3Configuration': {
                    'bucketArn': f'arn:aws:s3:::{s3_bucket}',
                    'inclusionPrefixes': [s3_prefix]
                }
            }
        )

        # Start ingestion job
        self.bedrock_agent.start_ingestion_job(
            knowledgeBaseId=knowledge_base_id,
            dataSourceId=response['dataSource']['dataSourceId']
        )

        return response['dataSource']['dataSourceId']

# Usage
kb_manager = KnowledgeBaseManager()

# Create knowledge base
kb_id = kb_manager.create_knowledge_base(
    name='australian-business-knowledge',
    description='Knowledge base for Australian business regulations and compliance'
)

# Add documents
kb_manager.add_data_source(
    kb_id,
    'my-business-docs-bucket',
    'compliance-documents/'
)

5. Assemble Complete Agent

class AustralianBusinessAgent:
    def __init__(self):
        self.bedrock_agent = boto3.client('bedrock-agent', region_name='ap-southeast-2')

    def create_agent(
        self,
        agent_name: str,
        foundation_model: str = 'anthropic.claude-v2'
    ) -> str:
        """Create complete Bedrock agent."""

        # Create agent
        agent_response = self.bedrock_agent.create_agent(
            agentName=agent_name,
            agentResourceRoleArn=self._get_agent_role_arn(),
            foundationModel=foundation_model,
            instruction=self._get_agent_instructions(),
            idleSessionTTLInSeconds=600,
            description='Australian business assistant for compliance and calculations'
        )

        agent_id = agent_response['agent']['agentId']

        # Create action groups
        self._create_action_groups(agent_id)

        # Associate knowledge base
        self._associate_knowledge_base(agent_id)

        # Prepare agent
        self.bedrock_agent.prepare_agent(agentId=agent_id)

        # Create alias
        alias_response = self.bedrock_agent.create_agent_alias(
            agentId=agent_id,
            agentAliasName='production'
        )

        return agent_id, alias_response['agentAlias']['agentAliasId']

    def _get_agent_instructions(self) -> str:
        return """You are an Australian business assistant specializing in:

1. ABN validation and ASIC lookups
2. GST calculations and tax guidance
3. Business registration requirements
4. Compliance reminders and deadlines
5. Australian business regulations

Guidelines:
- Use Australian English (organise, not organize)
- Format dates as DD/MM/YYYY
- Currency in AUD
- Reference Australian regulations and standards
- For complex legal/financial matters, recommend professional consultation
- Be helpful, professional, and accurate

When asked about business information:
1. First check if ABN validation is needed
2. Calculate GST if amounts are mentioned
3. Query knowledge base for compliance information
4. Provide clear, actionable answers"""

    def _create_action_groups(self, agent_id: str):
        """Create all action groups for agent."""

        action_groups = AgentActionGroups()

        # ABN and GST action group
        action_groups.create_action_group(
            agent_id=agent_id,
            action_group_name='business-tools',
            lambda_arn=self._get_lambda_arn(),
            api_schema=abn_validation_schema
        )

    def _associate_knowledge_base(self, agent_id: str):
        """Associate knowledge base with agent."""

        self.bedrock_agent.associate_agent_knowledge_base(
            agentId=agent_id,
            agentVersion='DRAFT',
            knowledgeBaseId=self._get_knowledge_base_id(),
            description='Australian business compliance knowledge',
            knowledgeBaseState='ENABLED'
        )

# Create agent
agent_builder = AustralianBusinessAgent()
agent_id, alias_id = agent_builder.create_agent('australian-business-assistant')

print(f"Agent created: {agent_id}")
print(f"Alias: {alias_id}")

Using the Agent

Basic Interaction

# Initialize agent
agent = BedrockAgent(agent_id, alias_id)

# Simple query
response = agent.invoke("Is ABN 53 004 085 616 valid?")
print(response['completion'])

# Multi-step task
response = agent.invoke("""
I need to invoice a client for $5,000 worth of consulting services.
1. Calculate the GST
2. Tell me the total amount to invoice
3. Explain what records I need to keep for tax purposes
""")

print(response['completion'])

Session Management

class AgentSession:
    def __init__(self, agent: BedrockAgent):
        self.agent = agent
        self.session_id = None
        self.history = []

    def chat(self, message: str) -> str:
        """Continue conversation in same session."""

        response = self.agent.invoke(message, self.session_id)

        # Store session ID for continuity
        self.session_id = response['session_id']

        # Track history
        self.history.append({
            'user': message,
            'agent': response['completion']
        })

        return response['completion']

    def get_history(self) -> list:
        """Get conversation history."""
        return self.history

# Usage
session = AgentSession(agent)

# Multi-turn conversation
response1 = session.chat("What do I need to register a business in NSW?")
response2 = session.chat("How much does it cost?")
response3 = session.chat("What about Victoria instead?")

# Agent maintains context across messages
for interaction in session.get_history():
    print(f"User: {interaction['user']}")
    print(f"Agent: {interaction['agent']}\n")

Advanced Agent Patterns

1. Multi-Agent Orchestration

class MultiAgentOrchestrator:
    def __init__(self):
        self.agents = {
            'compliance': BedrockAgent(compliance_agent_id, compliance_alias),
            'finance': BedrockAgent(finance_agent_id, finance_alias),
            'hr': BedrockAgent(hr_agent_id, hr_alias)
        }

    def route_query(self, query: str) -> dict:
        """Route query to appropriate specialist agent."""

        # Use LLM to classify query
        classification = self._classify_query(query)

        # Route to specialist agent
        agent_type = classification['category']
        agent = self.agents.get(agent_type)

        if agent:
            response = agent.invoke(query)
        else:
            response = self._handle_general_query(query)

        return {
            'agent_type': agent_type,
            'response': response['completion']
        }

    def _classify_query(self, query: str) -> dict:
        """Classify query to determine appropriate agent."""

        bedrock_runtime = boto3.client('bedrock-runtime', region_name='ap-southeast-2')

        prompt = f"""Classify this business query into one category:
- compliance: regulations, legal requirements, permits
- finance: accounting, tax, invoicing, expenses
- hr: employees, workplace, Fair Work, leave

Query: {query}

Respond with only the category name."""

        response = bedrock_runtime.invoke_model(
            modelId='anthropic.claude-v2',
            body=json.dumps({
                "prompt": f"\n\nHuman: {prompt}\n\nAssistant:",
                "max_tokens_to_sample": 20
            })
        )

        result = json.loads(response['body'].read())
        category = result['completion'].strip().lower()

        return {'category': category}

# Usage
orchestrator = MultiAgentOrchestrator()

response = orchestrator.route_query(
    "How many weeks of parental leave are employees entitled to?"
)

print(f"Routed to: {response['agent_type']}")
print(f"Response: {response['response']}")

2. Agent with Human-in-the-Loop

class HumanInLoopAgent:
    def __init__(self, agent: BedrockAgent):
        self.agent = agent
        self.pending_approvals = {}

    def invoke_with_approval(self, query: str, approval_required_actions: list) -> dict:
        """Invoke agent with human approval for certain actions."""

        response = self.agent.invoke(query)

        # Check if response requires approval
        if self._requires_approval(response, approval_required_actions):
            approval_id = self._request_approval(query, response)

            return {
                'status': 'pending_approval',
                'approval_id': approval_id,
                'preview': response['completion']
            }

        return {
            'status': 'completed',
            'response': response['completion']
        }

    def _requires_approval(self, response: dict, approval_actions: list) -> bool:
        """Check if response involves actions requiring approval."""

        # Parse response for action indicators
        response_text = response['completion'].lower()

        for action in approval_actions:
            if action.lower() in response_text:
                return True

        return False

    def _request_approval(self, query: str, response: dict) -> str:
        """Request human approval for action."""

        import uuid
        approval_id = str(uuid.uuid4())

        self.pending_approvals[approval_id] = {
            'query': query,
            'response': response,
            'timestamp': datetime.utcnow().isoformat(),
            'status': 'pending'
        }

        # Send notification (SNS, email, etc.)
        self._notify_approver(approval_id)

        return approval_id

    def approve_action(self, approval_id: str) -> dict:
        """Approve pending action."""

        if approval_id not in self.pending_approvals:
            return {'error': 'Invalid approval ID'}

        approval = self.pending_approvals[approval_id]
        approval['status'] = 'approved'

        return {
            'status': 'approved',
            'response': approval['response']['completion']
        }

# Usage
hitl_agent = HumanInLoopAgent(agent)

# Actions requiring approval
approval_actions = ['send invoice', 'create payment', 'submit form']

response = hitl_agent.invoke_with_approval(
    "Send invoice to client for $10,000",
    approval_actions
)

if response['status'] == 'pending_approval':
    print(f"Action requires approval: {response['approval_id']}")
    print(f"Preview: {response['preview']}")

    # Later, after human review
    final = hitl_agent.approve_action(response['approval_id'])
    print(f"Final response: {final['response']}")

3. Agent with Memory

class MemoryEnabledAgent:
    def __init__(self, agent: BedrockAgent):
        self.agent = agent
        self.dynamodb = boto3.resource('dynamodb', region_name='ap-southeast-2')
        self.memory_table = self.dynamodb.Table('agent-memory')

    def invoke_with_memory(self, user_id: str, query: str) -> dict:
        """Invoke agent with persistent memory."""

        # Retrieve user context
        context = self._get_user_context(user_id)

        # Enhance query with context
        enhanced_query = self._enhance_with_context(query, context)

        # Invoke agent
        response = self.agent.invoke(enhanced_query)

        # Update memory
        self._update_memory(user_id, query, response)

        return response

    def _get_user_context(self, user_id: str) -> dict:
        """Retrieve user context from DynamoDB."""

        try:
            response = self.memory_table.get_item(Key={'user_id': user_id})

            if 'Item' in response:
                return response['Item']['context']
        except:
            pass

        return {}

    def _enhance_with_context(self, query: str, context: dict) -> str:
        """Add relevant context to query."""

        if not context:
            return query

        context_str = f"""User context:
- Business name: {context.get('business_name', 'Not set')}
- ABN: {context.get('abn', 'Not set')}
- Industry: {context.get('industry', 'Not set')}
- Previous queries: {', '.join(context.get('recent_queries', [])[:3])}

Current query: {query}"""

        return context_str

    def _update_memory(self, user_id: str, query: str, response: dict):
        """Update user memory in DynamoDB."""

        # Get existing context
        context = self._get_user_context(user_id)

        # Update recent queries
        recent = context.get('recent_queries', [])
        recent.insert(0, query)
        recent = recent[:10]  # Keep last 10

        context['recent_queries'] = recent

        # Save to DynamoDB
        self.memory_table.put_item(
            Item={
                'user_id': user_id,
                'context': context,
                'last_interaction': datetime.utcnow().isoformat()
            }
        )

# Usage
memory_agent = MemoryEnabledAgent(agent)

# Agent remembers user context
response1 = memory_agent.invoke_with_memory(
    'user123',
    'My business ABN is 53 004 085 616'
)

# Later query uses remembered ABN
response2 = memory_agent.invoke_with_memory(
    'user123',
    'Calculate GST for a $1000 invoice'  # Agent knows the ABN
)

Monitoring and Observability

CloudWatch Integration

import boto3
from datetime import datetime

class AgentMonitoring:
    def __init__(self):
        self.cloudwatch = boto3.client('cloudwatch', region_name='ap-southeast-2')
        self.logs = boto3.client('logs', region_name='ap-southeast-2')

    def log_agent_interaction(
        self,
        agent_id: str,
        user_query: str,
        response: str,
        latency_ms: float,
        success: bool
    ):
        """Log agent interaction to CloudWatch."""

        # Custom metrics
        self.cloudwatch.put_metric_data(
            Namespace='BedrockAgents',
            MetricData=[
                {
                    'MetricName': 'Invocations',
                    'Value': 1,
                    'Unit': 'Count',
                    'Timestamp': datetime.utcnow(),
                    'Dimensions': [
                        {'Name': 'AgentId', 'Value': agent_id},
                        {'Name': 'Success', 'Value': str(success)}
                    ]
                },
                {
                    'MetricName': 'Latency',
                    'Value': latency_ms,
                    'Unit': 'Milliseconds',
                    'Timestamp': datetime.utcnow(),
                    'Dimensions': [
                        {'Name': 'AgentId', 'Value': agent_id}
                    ]
                }
            ]
        )

        # Detailed logs
        log_entry = {
            'timestamp': datetime.utcnow().isoformat(),
            'agent_id': agent_id,
            'user_query': user_query,
            'response_preview': response[:200],
            'latency_ms': latency_ms,
            'success': success
        }

        self.logs.put_log_events(
            logGroupName='/aws/bedrock/agents',
            logStreamName=agent_id,
            logEvents=[{
                'timestamp': int(datetime.utcnow().timestamp() * 1000),
                'message': json.dumps(log_entry)
            }]
        )

    def create_dashboard(self, agent_id: str):
        """Create CloudWatch dashboard for agent monitoring."""

        dashboard_body = {
            "widgets": [
                {
                    "type": "metric",
                    "properties": {
                        "metrics": [
                            ["BedrockAgents", "Invocations", {"stat": "Sum"}]
                        ],
                        "period": 300,
                        "stat": "Sum",
                        "region": "ap-southeast-2",
                        "title": "Agent Invocations"
                    }
                },
                {
                    "type": "metric",
                    "properties": {
                        "metrics": [
                            ["BedrockAgents", "Latency", {"stat": "Average"}]
                        ],
                        "period": 300,
                        "stat": "Average",
                        "region": "ap-southeast-2",
                        "title": "Average Latency"
                    }
                }
            ]
        }

        self.cloudwatch.put_dashboard(
            DashboardName=f'bedrock-agent-{agent_id}',
            DashboardBody=json.dumps(dashboard_body)
        )

Cost Optimisation

Agent Cost Structure

def calculate_agent_cost(
    num_invocations: int,
    avg_input_tokens: int,
    avg_output_tokens: int,
    foundation_model: str = 'claude-v2'
) -> dict:
    """Calculate Bedrock Agent costs (prices in AUD)."""

    # Model pricing per 1K tokens (example, converted to AUD)
    model_pricing = {
        'claude-v2': {
            'input': 0.01102,
            'output': 0.03306
        },
        'titan-text': {
            'input': 0.0004,
            'output': 0.0006
        }
    }

    pricing = model_pricing[foundation_model]

    # Calculate model costs
    input_cost = (avg_input_tokens / 1000) * pricing['input'] * num_invocations
    output_cost = (avg_output_tokens / 1000) * pricing['output'] * num_invocations

    # Agent orchestration costs (example)
    orchestration_cost = num_invocations * 0.0015  # Per invocation

    # Knowledge base query costs (if used)
    kb_cost = num_invocations * 0.0003  # Per query

    total_cost = input_cost + output_cost + orchestration_cost + kb_cost

    return {
        'model_cost': round(input_cost + output_cost, 2),
        'orchestration_cost': round(orchestration_cost, 2),
        'knowledge_base_cost': round(kb_cost, 2),
        'total_monthly_cost_aud': round(total_cost, 2)
    }

# Example: 10,000 invocations/month
cost = calculate_agent_cost(
    num_invocations=10_000,
    avg_input_tokens=800,
    avg_output_tokens=400,
    foundation_model='claude-v2'
)

print(f"Monthly cost: ${cost['total_monthly_cost_aud']} AUD")

Optimisation Strategies

1. Caching Common Queries:

from functools import lru_cache
import hashlib

@lru_cache(maxsize=1000)
def get_cached_response(query_hash: str):
    # Cache frequently asked questions
    pass

2. Prompt Optimisation:

# Reduce token usage with concise prompts
# Keep instructions clear but brief

3. Right-size Knowledge Base:

# Only include relevant documents
# Remove outdated content
# Optimize document chunking

Australian Compliance

Privacy and Data Handling

class CompliantAgent:
    def __init__(self, agent: BedrockAgent):
        self.agent = agent

    def invoke_with_pii_filtering(self, query: str) -> dict:
        """Invoke agent with PII filtering."""

        # Detect and mask PII before sending
        masked_query, pii_detected = self._mask_pii(query)

        # Invoke agent
        response = self.agent.invoke(masked_query)

        # Log PII usage
        if pii_detected:
            self._log_pii_usage(pii_detected)

        return response

    def _mask_pii(self, text: str) -> tuple:
        """Detect and mask PII in text."""

        import re

        pii_patterns = {
            'email': r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b',
            'phone': r'\b(?:\+?61|0)[2-478](?:[ -]?[0-9]){8}\b',
            'abn': r'\b\d{2}\s?\d{3}\s?\d{3}\s?\d{3}\b'
        }

        pii_found = []
        masked_text = text

        for pii_type, pattern in pii_patterns.items():
            matches = re.findall(pattern, text)
            if matches:
                pii_found.append({'type': pii_type, 'count': len(matches)})
                masked_text = re.sub(pattern, f'[{pii_type.upper()}]', masked_text)

        return masked_text, pii_found

Real-World Examples

Example 1: Customer Support Agent

# Agent that handles Australian e-commerce support
support_agent_instructions = """You are a customer support agent for an Australian e-commerce store.

Handle:
- Order tracking and status
- Returns and refunds (Australian Consumer Law)
- Product information and recommendations
- Delivery timeframes (Australia Post)
- Payment issues

Always:
- Check order status in database
- Validate Australian addresses
- Calculate GST correctly
- Reference Australian Consumer Guarantees
- Provide Australia Post tracking links
"""

Example 2: Compliance Assistant

# Agent that helps with Australian business compliance
compliance_agent_instructions = """You are an Australian business compliance assistant.

Help with:
- BAS lodgement reminders
- Fair Work compliance
- Regulatory requirements for regulated entities
- Privacy Act obligations
- Workplace health and safety

Check knowledge base for:
- Current regulations
- Lodgement deadlines
- Compliance checklists
- Required documentation
"""

Example 3: Property Management Agent

# Agent for Australian property management
property_agent_instructions = """You are a property management assistant for Australian real estate.

Manage:
- Tenant inquiries
- Lease agreements (state-specific)
- Maintenance requests
- Rental payments and bond
- Inspection scheduling

Apply:
- State residential tenancy laws
- Bond Authority requirements
- Fair Trading regulations
- Rental tribunal decisions
"""

Conclusion

Amazon Bedrock Agents enables Australian businesses to build sophisticated AI automation that can understand context, use tools, and take actions autonomously. By combining foundation models, action groups, and knowledge bases, you can create agents that handle complex workflows while maintaining security and compliance.

Key takeaways:

  • Agents orchestrate multi-step tasks autonomously
  • Action groups define what agents can do
  • Knowledge bases provide domain expertise
  • Guardrails ensure safe operation
  • Monitoring and human-in-the-loop provide control

CloudPoint helps Australian businesses design, implement, and deploy Bedrock Agents for customer support, business automation, and compliance assistance. We ensure your agents meet Australian regulatory requirements while delivering measurable business value.

Contact us for an AI Agent implementation consultation and automate your business workflows with confidence.


Ready to Build AI Agents?

CloudPoint helps Australian businesses implement Amazon Bedrock Agents that automate complex workflows and integrate with your systems. Get in touch to explore AI opportunities.

Learn more about our AI Services →