Kashif Naveed
Kashif Naveed

Production AI systems, designed for AWS.

Production-oriented AI projects across workflow automation, agentic systems and enterprise RAG.

Cloud provider
AI Application

AI Workflow Automation

Production-grade AI applications using Amazon Bedrock, Anthropic Claude and OpenAI models to automate operational workflows and provide intelligent organisational assistance.

Primary objective
Turn repetitive operational tasks into intelligent, auditable AI-assisted workflows.

AWS Architecture

Request → AI reasoning → enterprise services → governed response

Staff / User
Web, mobile or internal portal
API Gateway / FastAPI
Authentication · validation · routing
Amazon Bedrock
Claude · GPT · Guardrails · Model routing
AI Workflows
Summarisation · drafting · classification
Business APIs
Operational systems · data services
Audit & Monitoring
CloudWatch · CloudTrail · logs
AI capabilities
  • ✓ Claude-based reasoning
  • ✓ GPT model integration
  • ✓ Prompt orchestration
  • ✓ Structured outputs
  • ✓ Guardrails and validation
AWS services
Amazon Bedrock
Foundation models
Guardrails
Safety & policy
API Gateway
Edge routing
Lambda
Serverless compute
DynamoDB
State & history
Cognito
Authentication
CloudWatch
Metrics & logs
CloudTrail
Audit trail
Outcomes
  • ✓ Reduced manual processing
  • ✓ Faster information access
  • ✓ Consistent AI-assisted outputs
  • ✓ Auditable workflows
Sample code — governed Bedrock workflow

Invoke Claude on Amazon Bedrock with guardrails and structured output

workflows/summarize.py PYTHON
import json, time, logging, boto3
from botocore.config import Config
from jsonschema import validate, ValidationError

log = logging.getLogger("workflows")
cw  = boto3.client("cloudwatch")
bedrock = boto3.client(
    "bedrock-runtime", region_name="us-east-1",
    config=Config(retries={"max_attempts": 0}, read_timeout=30),  # we retry ourselves
)

MODEL = "anthropic.claude-sonnet-4-20250514-v1:0"
# Contract the model MUST satisfy — invalid output is rejected, not trusted
SCHEMA = {
    "type": "object",
    "required": ["summary", "priority", "next_action"],
    "properties": {
        "summary":     {"type": "string", "maxLength": 600},
        "priority":    {"enum": ["low", "medium", "high"]},
        "next_action": {"type": "string"},
    },
    "additionalProperties": False,
}

class GuardrailBlocked(Exception): ...

def _emit(name: str, value: float, unit="Count"):
    cw.put_metric_data(Namespace="AI/Workflows",
        MetricData=[{"MetricName": name, "Value": value, "Unit": unit}])

def summarize_ticket(ticket: dict, *, max_retries: int = 3) -> dict:
    prompt = f"""Summarise this operational ticket. Reply with ONLY JSON:
    {{"summary": str, "priority": "low|medium|high", "next_action": str}}
    Ticket: {json.dumps(ticket)}"""

    for attempt in range(1, max_retries + 1):
        started = time.perf_counter()
        try:
            resp = bedrock.invoke_model(
                modelId=MODEL,
                guardrailIdentifier="ops-guardrail",     # PII redaction + denied topics
                guardrailVersion="1",
                body=json.dumps({
                    "anthropic_version": "bedrock-2023-05-31",
                    "max_tokens": 512, "temperature": 0,
                    "messages": [{"role": "user", "content": prompt}],
                }),
            )
            payload = json.loads(resp["body"].read())

            # Guardrail intervened → fail closed, never return raw model text
            if payload.get("amazon-bedrock-guardrailAction") == "INTERVENED":
                _emit("GuardrailBlocked", 1)
                raise GuardrailBlocked("policy filter triggered")

            data = json.loads(payload["content"][0]["text"])
            validate(data, SCHEMA)                     # schema is the source of truth
            _emit("LatencyMs", (time.perf_counter() - started) * 1000, "Milliseconds")
            _emit("Success", 1)
            return data

        except (json.JSONDecodeError, ValidationError) as e:
            log.warning("invalid output (attempt %s): %s", attempt, e)
            if attempt == max_retries:
                _emit("ValidationFailure", 1)
                raise
            time.sleep(2 ** attempt * 0.2)     # exponential backoff
Performance & scale
Throughput, concurrency & latency
Serverless fan-out — model inference dominates the wall clock
Representative targets
50–100 /s
Workflow throughput
horizontal Lambda fan-out per Region
1,000 concurrent
Default Lambda concurrency
reserved / provisioned raises the ceiling
1.2 s
p50 latency
~400 ms TTFT with streaming enabled
3.5 s
p95 latency
bounded output (max_tokens = 512)
$0.003–0.02 /run
Cost per workflow
scales with input + output tokens
Latency profile (single workflow)
TTFT
~0.4 s
p50
~1.2 s
p95
~3.5 s
Guardrails & controls
Safety, correctness & auditability
Fail closed — an unsafe or malformed answer is never returned
Bedrock Guardrails
PII redaction, denied topics, content & profanity filters — fail closed on intervention.
Schema validation
Output must match a JSON Schema; invalid responses are retried, then rejected.
Prompt-injection hardening
Input length caps, delimiter isolation and instruction-precedence prompts.
IAM least privilege
Per-tenant roles scope each workflow to only the resources it needs.
Idempotency & retries
DynamoDB idempotency keys + exponential backoff prevent duplicate effects.
CloudTrail audit
Every invocation, guardrail block and failure is logged and alarmed in CloudWatch.
When this design fits
High-volume, repetitive tasks with a bounded, well-defined scope.
Second-scale latency is acceptable (not hard real-time).
Outputs have clear success criteria and can be schema-validated.
High-stakes actions keep a human in the loop for approval.
Spiky, unpredictable load suits serverless auto-scaling.
When to choose another approach
Hard real-time paths needing sub-100 ms, deterministic responses.
Jobs exceeding the 15-min Lambda limit — use Fargate / Step Functions.
Exact legal/financial calculations where LLM variance is unacceptable.
Very large context windows that inflate cost and latency per call.
Air-gapped / offline environments without managed model access.