Integration: Threat Modeling Workflow
This guide walks through a complete threat modeling workflow — from input through interview, structured output, and diagram generation.
End-to-End Workflow
Step 1: Prepare the Architecture Description
Write a clear description of the system being modeled. Include:
- Components and their roles
- Data flows between components
- Trust boundaries
- External dependencies
- Authentication and authorization mechanisms
- Data classification (what is sensitive)
Example input:
System: Customer Portal API
Components:
- React SPA served from CloudFront
- API Gateway (Kong) handling JWT authentication
- User Service (Node.js, Express) — account management, PostgreSQL
- Payment Service (Java, Spring Boot) — payment processing via Stripe API, PostgreSQL
- Notification Service (Python, FastAPI) — email via SendGrid, reads from SQS queue
- All services in EKS (Kubernetes) in a private VPC
- Redis for session caching
- S3 for document storage with pre-signed URLs
Trust boundaries:
- Public internet (browser to CDN)
- DMZ (CDN, API Gateway)
- Private network (microservices, databases)
- External (Stripe, SendGrid, SQS)
Step 2: Run the Threat Model Interview
Start a conversation with the threat modeling interview prompt as the system prompt.
import anthropic
client = anthropic.Anthropic()
with open("prompts/threat-modeling/03-threat-modeling-interview-opus.md") as f:
interview_prompt = f.read()
messages = []
messages.append({
"role": "user",
"content": "I need to threat model our Customer Portal API. Here is the architecture:\n\n[paste architecture description]"
})
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=4096,
system=interview_prompt,
messages=messages
)
# The model asks its first question — continue the multi-turn conversation
print(response.content[0].text)
The interview typically runs 15-30 questions, covering:
- Data classification and sensitivity
- Authentication mechanisms and session management
- Authorization models and access control
- Network architecture and trust boundaries
- Logging, monitoring, and incident response
- Third-party dependencies and supply chain risks
- Deployment and infrastructure security
Step 3: Get Structured Output
At the end of the interview, the model produces a structured threat model. Request CycloneDX-formatted output:
Please produce the final threat model in CycloneDX JSON format.
Example output structure:
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"serialNumber": "urn:uuid:...",
"version": 1,
"metadata": {
"timestamp": "2026-02-24T00:00:00Z",
"component": {
"type": "application",
"name": "Customer Portal API"
}
},
"vulnerabilities": [
{
"id": "THREAT-001",
"description": "JWT token theft via XSS in React SPA",
"analysis": {
"state": "exploitable",
"detail": "If an attacker achieves XSS in the React frontend, they can steal JWT tokens from localStorage and impersonate the user."
},
"ratings": [
{
"method": "other",
"severity": "high",
"score": 7.5
}
],
"recommendation": "Store JWT tokens in HttpOnly cookies instead of localStorage. Implement Content Security Policy headers."
}
]
}
Step 4: Generate a Diagram
Feed the architecture description to a diagram generator prompt:
with open("prompts/threat-modeling/12-threat-model-diagram-generator-opus.md") as f:
diagram_prompt = f.read()
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=8192,
system=diagram_prompt,
messages=[
{"role": "user", "content": architecture_description}
]
)
diagram_output = response.content[0].text
# Extract the Mermaid diagram from the output
# Save to a .mmd file for rendering
with open("threat-model-diagram.mmd", "w") as f:
f.write(diagram_output)
Example Mermaid output:
Step 5: Render and Export
Render the Mermaid diagram to SVG:
npx @mermaid-js/mermaid-cli -i threat-model-diagram.mmd -o threat-model-diagram.svg
Embed in your repository:
<!-- docs/threat-model.md -->
## Threat Model Diagram

## STRIDE Threat Matrix
| Component | S | T | R | I | D | E |
|-----------|---|---|---|---|---|---|
| API Gateway | JWT spoofing | Token tampering | No request logging | Config exposure | Rate limiting gap | Auth bypass |
| User Service | Session hijack | DB tampering | Missing audit log | PII in logs | Query DoS | IDOR |
| Payment Service | Stripe key theft | Amount tampering | No payment log | Card data exposure | Stripe rate limit | Privilege escalation |
Automation Script
Combine all steps into a single script:
#!/usr/bin/env python3
"""Run a complete threat model workflow from architecture description."""
import anthropic
import json
import sys
def run_threat_model(architecture_path, output_dir):
client = anthropic.Anthropic()
with open(architecture_path) as f:
architecture = f.read()
# Step 1: Generate diagram
with open("prompts/threat-modeling/12-threat-model-diagram-generator-opus.md") as f:
diagram_prompt = f.read()
diagram_response = client.messages.create(
model="claude-opus-4-6",
max_tokens=8192,
system=diagram_prompt,
messages=[{"role": "user", "content": architecture}]
)
with open(f"{output_dir}/diagram.mmd", "w") as f:
f.write(diagram_response.content[0].text)
# Step 2: Generate STRIDE analysis
with open("prompts/threat-modeling/06-stride-api-threat-modeling-opus.md") as f:
stride_prompt = f.read()
stride_response = client.messages.create(
model="claude-opus-4-6",
max_tokens=8192,
system=stride_prompt,
messages=[{"role": "user", "content": architecture}]
)
with open(f"{output_dir}/stride-analysis.md", "w") as f:
f.write(stride_response.content[0].text)
print(f"Outputs written to {output_dir}/")
if __name__ == "__main__":
run_threat_model(sys.argv[1], sys.argv[2])
python threat-model.py docs/architecture.md docs/threat-model/