Overview

GetMyTwin is a structural observability tool for AI systems. You describe an architecture — agents, tools, models, flows — and the engine produces a living visual twin, a fragility index, knockout simulations, system-health metrics, and recommendations.

Two readings: structure (FI, SPOFs, bridges, system health) and economics (cost per route, token hotspots, expensive loops). The same architecture, two lenses.

Key concepts

tri(e)
Shared neighbours of an edge's endpoints. tri = 0 → no redundancy.
Fragility Index (FI)
100 × (AF + 0.5 × F) / total_edges. Lower is better.
Resilience
100 − FI. The number we surface in the UI.
SPOF
Node whose removal raises FI by > 15 points.
Bridge
Edge whose removal disconnects the graph (Tarjan).
Cognitive Load
Per-node connection density vs. the busiest node.
Routing Entropy
Shannon entropy of betweenness centrality — path diversity.
Isolation Risk
Per-node share of always-fragile / bridge connections.

Quick start

  1. Open getmytwin.io and paste any supported format into the textarea — or pick an example.
  2. The format is auto-detected (within ~500 ms). A chip below the textarea shows what we found.
  3. Click Analyze architecture → land on /twin/[id].
  4. Hover any node for cognitive-load / isolation-risk; click a node for a knockout simulation; apply recommendations to see the graph reshape in real time.
  5. Toggle Cost Overlay for a tokens / dollars heat map, or Chaos Mode for a random-failure simulation.
  6. Hit View full report for the printable PDF view, or Compare before / after to share a diff URL.

GetMyTwin YAML — full reference

The native format. Every field except name on a node is optional. Unknown nodes referenced by an edge are auto-created.

Minimal example

system:
  name: My System

agents:
  - id: planner
    tools: [search, db]

flows:
  - from: user
    to: planner

Top-level shape

FieldTypeNotes
system.namestringDisplay title.
system.traffic.requests_per_daynumberOptional — unlocks daily / monthly cost estimates.
agents[]listSmart routing nodes.
tools[]listExternal services / DBs.
models[]listLLMs (optional).
data[]listData stores (optional).
flows[]listEdges between nodes — { from, to }.

Node fields

FieldTypeNotes
idstringRequired. Used as graph key.
labelstringDisplay name (defaults to titlecased id).
toolsstring[]Agents only — automatically creates the agent → tool edges.
costobjectSee Cost annotations.
rolestringModels — free-form description.

Customer Support example (annotated)

system:
  name: Customer Support AI
  traffic:
    requests_per_day: 500

agents:
  - id: triage_agent
    tools: [crm, email, vector_db]
    cost:
      tokens_per_call: 2500
      model: gpt-4
      avg_latency_ms: 800
      cost_per_call_usd: 0.030
  - id: refund_agent
    tools: [stripe, crm]
  - id: legal_agent
    tools: [policy_db]

tools:
  - id: crm
  - id: stripe
  - id: policy_db

flows:
  - from: user
    to: triage_agent
  - from: triage_agent
    to: refund_agent
  - from: triage_agent
    to: legal_agent

user is created implicitly the first time it's referenced. Edges are undirected for the structural analysis; cost route enumeration follows the order of the flows block.

Cost annotations

Every node can carry a cost block. Anything missing falls back to a default keyed on type + model hint, marked in the UI with an italic ~ prefix.

Schema

cost:
  tokens_per_call: 2500        # integer
  cost_per_call_usd: 0.030     # float
  avg_latency_ms: 800          # integer
  model: gpt-4                 # optional hint (drives defaults)

Traffic (for daily / monthly estimates)

system:
  name: ...
  traffic:
    requests_per_day: 500

Default estimates

Picked when no explicit cost is provided. The model hint matches on substring (haiku, sonnet, mini, gpt-4, gpt-5).

MatchTokens / call$ / callLatency
agent (default)2,000$0.020600 ms
agent + gpt-4 / gpt-53,000$0.030800 ms
agent + mini1,500$0.005300 ms
agent + claude-sonnet2,500$0.020600 ms
agent + claude-haiku1,000$0.003200 ms
tool (default)0$0.005200 ms
tool id contains db / sql / postgres0$0.00150 ms
tool id contains vector / embedding0$0.00280 ms
tool id contains api / webhook / http0$0.010500 ms
tool id contains email / mail / smtp0$0.003300 ms

What the engine derives

  • Per-request stats: average tokens, cost, latency across enumerated routes (capped at 50).
  • Daily / monthly: requires traffic.requests_per_day.
  • Token hotspots: route-weighted contribution percentage. Tiers at 25 / 50 / 75 %.
  • Expensive loops: 3-cycles whose total per-iteration cost ≥ $0.01.

Multi-format import

Drop any of the formats below into the textarea and detection takes over. Non-native formats don't carry cost data, so the cost overlay falls back to defaults.

LangGraph (JSON)

{
  "name": "Research Assistant",
  "entry_point": "supervisor",
  "nodes": [
    { "id": "supervisor", "type": "agent", "data": { "name": "Supervisor" } },
    { "id": "researcher", "type": "agent" },
    { "id": "web_search", "type": "tool" }
  ],
  "edges": [
    { "source": "supervisor", "target": "researcher" },
    { "source": "researcher", "target": "web_search" }
  ]
}

entry_point is wired up as user → entry. Node types map to GetMyTwin types (agent / tool / model / data / external) by keyword.

LangGraph (Python)

graph.add_node("supervisor", supervisor_fn)
graph.add_node("researcher", researcher_fn)
graph.add_edge("supervisor", "researcher")
graph.add_conditional_edges("researcher", router, {
  "search": "web_search",
  "answer": END,
})
graph.set_entry_point("supervisor")

Regex-only — we do not execute your Python. Node names are inferred from id substrings (db, llm, agent, …).

CrewAI (YAML)

crew:
  name: Content Pipeline

agents:
  - role: Researcher
    tools: [web_search, scrape]
    llm: gpt-4
  - role: Writer
    tools: [file]
    llm: gpt-4

tasks:
  - description: Gather sources
    agent: Researcher
  - description: Draft article
    agent: Writer
    context:
      - Gather sources

agents[].role → agent node; agents[].tools[] → tool nodes; agents[].llm → model node connected to the agent; tasks[].context → resolves to agent → agent dependency edges.

OpenAI Agents SDK

# Python
triage = Agent(
    name="Triage",
    model="gpt-4.1",
    tools=[search, calendar],
    handoffs=[billing, support],
)
// JSON
{
  "agents": [{
    "name": "Triage",
    "model": "gpt-4.1",
    "tools": ["search", "calendar"],
    "handoffs": ["billing", "support"]
  }]
}

tools → tool nodes. model → model node attached to the agent. handoffs → agent-to-agent edges.

MCP server config (JSON)

{
  "mcpServers": {
    "filesystem": { "command": "npx", "args": ["..."] },
    "github":     { "command": "npx", "args": ["..."] }
  }
}

Renders as an implicit MCP Client agent connected to each server. Star topology — every edge is always-fragile, making MCP setups a textbook case for the "add a fallback" recommendation.

Tips & FAQ

Tips

  • Auto-detection: paste any supported format and GetMyTwin figures out which one it is on its own.
  • File upload: click Browse file or drag-drop a .yaml, .yml, .json, .py, or .txt file.
  • Maximum file size: 500 KB.
  • Cost data is optional but enables the Cost Overlay, hotspot detection, and loop-guard recommendations.

FAQ

Is my YAML stored anywhere?

Analyses live in process memory only. They survive page reloads while the server is up but are wiped on every deploy. Auth tables (User / VerificationToken) are the only persisted data. There is no team or sharing layer — the only persistence vector is the session id in your URL.

What's the difference between an SPOF and a bridge?

A bridge is an edge whose removal disconnects the graph. A SPOF is a node whose removal raises the FI by > 15 points (which usually also disconnects the graph, but doesn't have to). Bridges are about connectivity; SPOFs are about resilience.

How does "Apply" recompute the FI?

Every recommendation carries a structural change payload (nodes + edges to add). The client merges all applied changes into the original architecture, re-runs the FI engine in the browser, and rerenders. The diff page (/diff/[id]) does the same off the URL params.

How are costs estimated when I don't provide them?

See the Cost annotations table. We match on node type and on substrings in the id (or the cost.model hint). Anything filled from defaults renders as italic ~$value in the UI.

Why is the Chaos Mode mutually exclusive with Cost Overlay?

Both modes re-skin the graph — Chaos colors edges grey-dashed as they fail, Cost colors them by route price. Showing both at once would muddle the visual signal, so toggling one resets the other.

What about graphs without a `user` node?

The cost engine picks degree-1 leaves as fallback sources. For MCP / star topologies, the central client node is picked. Structural analyses (FI, SPOF, bridges) don't depend on a user node at all.

My format isn't detected correctly.

Use the Change format dropdown below the textarea to force a specific format. Auto-detection is a best effort — for ambiguous inputs (e.g. JSON shaped like both CrewAI and OpenAI Agents) it falls back to a reasonable guess that you can override manually.

Can I mix formats in a single input?

No — each input is parsed as a single format. Use GetMyTwin YAML if you want the richest feature set (cost annotations, traffic, model hints). Other formats are great for instant imports but lose cost data, which then falls back to defaults.

How are connections created?

Two sources, merged and deduplicated:

  • agents[].tools — every tool listed under an agent produces an agent → tool edge automatically.
  • flows[] — explicit { from, to } pairs add edges between any two nodes.

Edges are treated as undirected by the structural engine. The cost engine uses flow order for route enumeration.

What's the maximum graph size?

GetMyTwin handles graphs up to roughly 200 nodes comfortably. Larger graphs may slow down the visualization (React Flow layout + Brandes betweenness centrality both have quadratic behaviour on dense inputs).