// Canonical example for the book: customer support agentic platform.

person = kind "Person"
system = kind "System"
container = kind "Container"
component = kind "Component"
database = kind "Database"
queue = kind "Queue"

overview {
  summary "Agentic automation for e-commerce support: triage, investigation, and resolution"
  audience "Support operations, product, platform engineering"
  scope "Ticket triage, refunds, missing orders, chargebacks, proactive outreach"
  goals ["Reduce resolution time", "Ensure approvals", "Maintain auditability"]
  nonGoals ["General-purpose RPA outside support domain"]
  risks ["Prompt injection", "PII leakage", "Incorrect refunds", "Vendor lock-in"]
}

customer = person "Customer" {
  description "Reports issues, requests refunds, tracks orders"
  metadata { tags ["R1"] }
}
supportAgent = person "Support Agent" {
  description "Approves sensitive actions, handles escalations"
  metadata { tags ["R3"] }
}

commerce = system "E-commerce" {
  description "Order management, catalog, and shipping integrations"

  shopFrontend = container "Web/App Frontend" {
    technology "React/Next.js"
    description "Customer portal for orders and support"
    version "2.3.0"
    tags ["customer","frontend"]
    scale { min 3 max 12 metric "cpu > 70%" }
  }

  orderAPI = container "Order Service" {
    technology "Node.js"
    description "Order management and fulfillment API"
    scale { min 4 max 10 }
    slo { latency { p95 "300ms" p99 "800ms" } }
    ordersRead = component "Orders Read" {
      description "Order read endpoints"
      technology "Express"
    }
    ordersWrite = component "Orders Write" {
      description "Order write endpoints"
      technology "Express"
      metadata { tags ["R4"] }
    }
  }

  ordersDB = database "Orders Database" {
    technology "PostgreSQL"
    description "Canonical source of order and payment state (shared read-only for agentic investigations)"
    metadata { shared "true" }
  }

  shippingAPI = container "Shipping Integration" {
    technology "Go"
    description "Carrier integrations and tracking"
  }
}

support = system "Support Operations" {
  description "Ticketing, CRM, and communications"

  ticketing = container "Ticketing System" {
    technology "Zendesk"
    description "Customer support tickets and workflows"
    ticketAPI = component "Ticket API" {
      description "Ticket CRUD and macros"
      technology "Zendesk API"
      metadata { tags ["R1"] }
    }
  }

  cRM = container "CRM" {
    technology "Salesforce"
    description "Customer profiles and entitlements"
    cRMAPI = component "CRM API" {
      description "Contact, case, entitlement APIs"
      technology "Salesforce API"
    }
  }

  email = container "Transactional Email" {
    technology "SendGrid"
    description "Outbound communications and notifications"
    emailAPI = component "Email API" {
      description "Email send and templates"
      technology "SendGrid API"
    }
  }
}

agentic = system "Agentic Platform" {
  description "Planning, tool-use, execution, memory, and governance for support automation"

  aPI = container "Agent Gateway" {
    technology "TypeScript/Node.js"
    description "Ingress, contracts, streaming of results"
    version "1.1.0"
    tags ["api","backend"]
    scale { min 2 max 6 metric "cpu > 65%" }
    slo { latency { p95 "1200ms" p99 "2500ms" } }
    requestHandler = component "Request Handler" {
      description "Validates and receives tasks"
      technology "Express Middleware"
      metadata { tags ["R1"] }
    }
    streamServer = component "Stream Server" {
      description "SSE/WebSocket streams"
      technology "ws"
      metadata { tags ["R2"] }
    }
  }

  orchestrator = container "Task Orchestrator" {
    technology "Go"
    description "Lifecycle control, routing, safety checks, trace context"
    plannerRouter = component "Planner Router" {
      description "Planner routing and retries"
      technology "Go"
      metadata { tags ["R1"] }
    }
    safetyGate = component "Safety Gate" {
      description "Pre-execution guardrails"
      technology "Go"
      metadata { tags ["R3"] }
    }
    memoryManager = component "Memory Manager" {
      description "Retrieval hooks and updates"
      technology "Go"
      metadata { tags ["R1"] }
    }
    slo { availability { target "99.9%" window "30 days" } }
  }

  planner = container "Planning Agent Service" {
    technology "Python"
    description "Generates plans and selects tools"
    scale { min 3 max 10 }
    reActPlanner = component "ReAct Planner" {
      description "Reason+Act planning"
      technology "LangChain"
      metadata { tags ["R1"] }
    }
    toTPlanner = component "ToT Planner" {
      description "Tree-of-Thought for complex cases"
      technology "LangChain"
    }
    toolSelector = component "Tool Selector" {
      description "Tool allowlist and selection"
      technology "Python"
      metadata { tags ["R3"] }
    }
  }

  tools = container "Support Tools" {
    technology "Mixed"
    description "External tools invoked by agents"
    webBrowser = component "Web Browser" {
      description "Web search and scraping"
      technology "Playwright"
      metadata { tags ["R1"] }
    }
    databaseQuery = component "Database Query" {
      description "Structured data access"
      technology "SQLAlchemy"
      metadata { tags ["R1"] }
    }
    codeRunner = component "Code Runner" {
      description "Ephemeral code execution"
      technology "Python Sandbox"
      metadata { tags ["R3"] }
    }
    emailSender = component "Email Sender" {
      description "Templated email dispatch"
      technology "SMTP"
      metadata { tags ["R1"] }
    }
  }

  executor = container "Execution Sandbox" {
    technology "Docker"
    description "Network-restricted sandbox for code execution"
    sandboxRuntime = component "Sandbox Runtime" {
      description "Runtime with quotas"
      technology "gVisor"
      metadata { tags ["R3"] }
    }
    traceEmitter = component "Trace Emitter" {
      description "Execution traces"
      technology "OpenTelemetry"
      metadata { tags ["R2"] }
    }
  }

  monitor = container "Telemetry & Policy" {
    technology "Go"
    description "Metrics, logs, policy evaluation, audit trail"
    policyEngine = component "Policy Engine" {
      description "Evaluates enforcement rules"
      technology "OPA"
      metadata { tags ["R3"] }
    }
    metricsCollector = component "Metrics Collector" {
      description "Latency, error rate, throughput"
      technology "Prometheus"
      metadata { tags ["R2"] }
    }
    auditLog = component "Audit Log" {
      description "Immutable audit trail"
      technology "TimescaleDB"
      metadata { tags ["R3", "R1"] }
    }
  }

  vectorDB = database "Vector Store" {
    technology "Pinecone/Weaviate"
    description "Long-term memory for retrieval"
  }

  cache = database "Context Cache" {
    technology "Redis"
    description "Short-term context, rate limits, throttles"
  }

  taskQueue = queue "Agent Tasks" {
    technology "Kafka/SQS"
    description "Decouples planning from execution"
  }

  aPI.requestHandler -> orchestrator "Submit task"
  orchestrator.plannerRouter -> planner "Route to planning agent"
  orchestrator.plannerRouter -> planner.toTPlanner "Escalate complex cases"
  planner.toolSelector -> tools "Invoke tool"
  executor.traceEmitter -> monitor "Send traces"

  aPI.requestHandler -> orchestrator.plannerRouter "Dispatch task"
  orchestrator.plannerRouter -> planner.reActPlanner "Request plan"
  planner.toolSelector -> tools.webBrowser "Search"
  planner.toolSelector -> tools.databaseQuery "Query"
  planner.toolSelector -> tools.codeRunner "Prototype"
  planner.toolSelector -> tools.emailSender "Notify"
  planner.reActPlanner -> orchestrator.memoryManager "Retrieve context"
  orchestrator.safetyGate -> monitor.policyEngine "Evaluate"
  orchestrator.plannerRouter -> executor.sandboxRuntime "Execute step"
  executor.traceEmitter -> monitor.auditLog "Emit traces"
  planner.reActPlanner -> vectorDB "Write embeddings"
  planner.reActPlanner -> cache "Warm context"
  orchestrator.plannerRouter -> taskQueue "Enqueue execution"
  taskQueue -> executor.sandboxRuntime "Dequeue"
  monitor.metricsCollector -> aPI.streamServer "Stream telemetry"
}

external = system "External Services" {
  description "Third-party APIs"
  payments = container "Stripe" {
    technology "Stripe API"
    description "Payment processing"
    metadata { tags ["external", "R4"] }
  }
  commerceHost = container "Shopify" {
    technology "Shopify API"
    description "E-commerce platform"
    metadata { tags ["external"] }
  }
  searchAPI = container "Search API" {
    technology "Elasticsearch"
    description "Product search"
    metadata { tags ["external"] }
  }
  carriers = container "Carrier APIs" {
    technology "FedEx/UPS API"
    description "Shipping tracking"
    metadata { tags ["external"] }
  }
}

customer -> commerce.shopFrontend "Places orders"
customer -> commerce "Shops"
commerce.shopFrontend -> commerce.orderAPI "Create order"
commerce.orderAPI -> commerce.shippingAPI "Shipping quote"
commerce.orderAPI -> commerce.ordersDB "Persist order"
commerce.orderAPI.ordersRead -> commerce.ordersDB "Read order"
commerce.orderAPI.ordersWrite -> commerce.ordersDB "Write order"
customer -> support.ticketing "Submits ticket"
customer -> support "Requests support"
supportAgent -> support.ticketing "Works tickets"
supportAgent -> agentic.aPI "Approves actions"
supportAgent -> agentic "Uses automation"
support.ticketing -> support.cRM "Lookup customer"
agentic.aPI -> support.ticketing.ticketAPI "Ticket CRUD"
agentic.aPI -> support.email "Notify customer"
agentic -> external "Calls third-party APIs"

agentic.aPI -> support.ticketing "Create/update tickets"
agentic.tools.databaseQuery -> commerce.ordersDB "Read order state"
agentic.tools.webBrowser -> external.searchAPI "Query"
agentic.tools.webBrowser -> external.carriers "Track shipment"
agentic.tools.emailSender -> support.email.emailAPI "Send email"
support.cRM.cRMAPI -> agentic.tools.databaseQuery "queries via"
agentic.tools.codeRunner -> agentic.executor "Invoke code"
agentic.tools.databaseQuery -> external.commerceHost "Fetch order"
agentic.tools.databaseQuery -> external.payments "Payment lookup"

R1 = requirement functional "Automate triage and investigation for top 5 issue types"
R2 = requirement performance "Reduce average resolution time by 40%"
R3 = requirement security "Mask PII in prompts and logs"
R4 = requirement constraint "Refunds over $100 require human approval"

R1 -> agentic.aPI.requestHandler "Satisfied by"
R2 -> agentic.monitor.metricsCollector "Measured by"
R3 -> agentic.orchestrator.safetyGate "Enforced by"
R4 -> agentic.monitor.policyEngine "Evaluated by"

ADR001 = adr "Adopt ReAct for planning" {
  status "accepted"
  context "Reliable tool selection and iterative refinement needed"
  decision "Use ReAct; fall back to ToT for complex cases"
  consequences "Higher success rate; increased token usage"
}
ADR002 = adr "Use vector DB for memory" {
  status "accepted"
  context "Require retrieval-augmented planning and case recall"
  decision "Persist embeddings and traces to VectorDB"
  consequences "Better recall; vendor lock-in risk"
}
ADR003 = adr "Introduce task queue" {
  status "accepted"
  context "Decouple planning from execution and absorb spikes"
  decision "Use Kafka/SQS between orchestrator and executor"
  consequences "Eventual consistency; simplified scaling"
}
ADR004 = adr "Human-in-the-loop approvals" {
  status "accepted"
  context "Financial risk and customer trust require oversight"
  decision "Require agent approval for sensitive operations"
  consequences "Adds latency; improves correctness and compliance"
}

RefundPolicy = policy "Refunds over $100 require approval" {
  category "finance"
  enforcement "required"
}
PIIProtection = policy "Mask PII in prompts and logs" {
  category "security"
  enforcement "required"
}
ToolAccessPolicy = policy "Restrict tools to allowlist" {
  category "governance"
  enforcement "required"
}

constraints {
  "Executor runs in sandbox with default egress blocked"
  "All tool calls pass SafetyGate"
  "Only allowlisted domains for WebBrowser"
  "DatabaseQuery limited to read-only for OrdersDB"
}

conventions {
  "Emit JSON traces with step and ticket IDs"
  "Use typed contracts for agent ingress and approvals"
  "Tag sensitive relations with [HumanInLoop]"
}

TicketTriage = scenario "Triage incoming ticket" {
  step customer -> support.ticketing "Submit"
  step support.ticketing -> agentic.aPI "Webhook"
  step agentic.aPI -> agentic.orchestrator "Dispatch"
  step agentic.orchestrator -> agentic.planner "Plan"
  step agentic.planner -> agentic.tools.databaseQuery "Order lookup"
  step agentic.planner -> agentic.tools.webBrowser "Carrier tracking"
  step agentic.orchestrator -> agentic.executor "Execute macro"
  step agentic.executor -> agentic.monitor "Trace"
  step agentic.aPI -> support.ticketing "Update"
}

RefundInvestigation = scenario "Process refund request" {
  step support.ticketing -> agentic.aPI "Refund requested"
  step agentic.aPI -> agentic.orchestrator "Dispatch"
  step agentic.orchestrator -> agentic.planner "Plan investigation"
  step agentic.planner -> agentic.tools.databaseQuery "Payment lookup"
  step agentic.planner -> agentic.tools.databaseQuery "Order state"
  step agentic.orchestrator -> agentic.monitor.policyEngine "Evaluate policy"
  step supportAgent -> agentic.aPI "Approve refund"
  step agentic.aPI -> external.payments "Initiate refund"
  step agentic.aPI -> support.email "Notify customer"
}

LostPackage = scenario "Handle not received order" {
  step customer -> support.ticketing "Report issue"
  step agentic.aPI -> agentic.orchestrator "Dispatch"
  step agentic.planner -> agentic.tools.webBrowser "Carrier tracking"
  step agentic.planner -> agentic.tools.emailSender "Proactive outreach"
  step agentic.aPI -> support.ticketing "Add tracking info"
}


TriageFlow = flow "Data flow for triage" {
  step agentic.planner -> agentic.tools.databaseQuery "Order lookup"
  step agentic.tools.databaseQuery -> agentic.planner "Order details"
  step agentic.planner -> agentic.tools.webBrowser "Carrier query"
  step agentic.tools.webBrowser -> agentic.planner "Tracking data"
  step agentic.planner -> agentic.tools.emailSender "Email"
  step agentic.tools.emailSender -> support.email "Send"
}
