Skip to main content
Blast Radius answers “what actually depends on this?” for a single resource — a prompt, an agent, a guardrail policy, an evaluator, a dataset, a model, or an alert — by walking a dependency graph built from both your project’s configuration and its real production traffic. It isn’t a standalone dashboard page today. It surfaces in two places where the answer changes what you’d do next:
  • Releasing a prompt — the confirmation dialog for promoting a version to production shows an impact summary before you commit. Advisory only; it never blocks the release.
  • Deleting an evaluator — the delete confirmation shows the same summary plus a full dependents table, and it does block: if the evaluator has any dependents (or the check fails to load), you have to explicitly acknowledge before Delete becomes clickable.
A full graph visualization and a standalone Blast Radius page are on the roadmap but not built yet. Today the graph is only consumed through the two integration points above, and directly through the API described below.

Declared vs. observed edges

Every dependency in the graph is one of two kinds, and the UI keeps them visually distinct rather than collapsing them into one number: The distinction matters in both directions: a prompt configured as a dependency of six agents but only ever called by one is a much smaller real blast radius than the declared graph alone suggests. Conversely, a dependency nobody explicitly configured but that shows real call volume is exactly the kind of undocumented coupling this feature exists to surface. A dependent can be reached through more than one edge (for example, a prompt embedded in two different parent prompts, both called by the same agent). When that happens, hasObservedTraffic, totalCallVolume30d, and totalCostUsd30d on that dependent are summed across every inbound edge feeding it from within the blast radius — not just the one edge that happened to be discovered first. A dependent reached only through a declared edge can still show real observed traffic, if another edge into it (from elsewhere in the same blast radius) is observed.

Dependency direction

Every edge is { from, to }, and to depends on from — read it as “changing from affects to”: So “what breaks if I change this prompt?” is answered by walking dependents from the prompt — which surfaces every agent that calls it, directly or transitively.

Node ids

A node id is <kind>:<key> — for example prompt:support-reply or evaluator:3f9c.... Keys are names for prompts, agents, and models, and UUIDs for row-backed kinds (evaluators, guardrail policies, datasets, alerts). Because a key can itself contain a colon or a slash (a prompt legitimately named checkout/v2 produces the id prompt:checkout/v2), the id always travels as the node query parameter — never a URL path segment.

Depth, node, and time-window caps

A blast radius is a breadth-first walk from the root node, bounded on three axes so a hub resource with hundreds of dependents (or a genuine dependency cycle — agent-to-agent delegation produces real ones) can’t turn one request into an unbounded scan: truncated: true in the response means the walk hit one of these caps and the graph genuinely continues beyond it — not merely that the graph happened to end exactly at the cap. If depth 3 reaches every dependent and stops naturally, truncated is false even though depth 3 was the limit checked.

Response shape

dependents[].totalCallVolume30d and totalCostUsd30d sum to impact.callVolume30d / impact.cost30dUsd across the whole response — the per-node numbers and the headline number are the same aggregation at two grains, not two separately-computed figures that can drift apart. computedAt marks the moment this response’s graph was built. Every request computes fresh — there’s no caching in front of this endpoint today — so computedAt is effectively “now,” modulo the small delay before a trace becomes queryable. It’s still shown on every card and table because a number with no timestamp reads as unexplainably stale the first time it lags even slightly behind a dashboard refresh.
impact.slosAtRisk and impact.gates are always empty arrays today. They’re reserved fields for an SLO model that hasn’t shipped yet — present so the response shape won’t need to change later, not because either is currently populated. Don’t build against them expecting real data.

Where it’s not (yet)

  • No standalone Blast Radius page. The graph is only reachable through the two integration points above and the API directly.
  • No graph visualization. GET /projects/:id/graph returns the full raw graph (nodes + edges) for a project, sized for a future visualization — nothing in the dashboard renders it yet.
  • Tool and HTTP-target nodes aren’t in the graph. Only prompts, agents, models, guardrail policies, evaluators, datasets, and alerts are covered. MCP tool calls and HTTP targets are candidates for a later pass.

API

Both endpoints require a dashboard session (browser cookie) with the dashboard:read permission — not an x-api-key request. See the Blast Radius group in the API Reference for full parameter and response documentation.
Get the blast radius for one node
A malformed node (missing the kind:key separator) returns 400. A well-formed id for a resource that doesn’t exist in the project — or that belongs to a different project — returns 404; the two cases (typo vs. wrong project) are deliberately indistinguishable in the response, so a cross-project id can’t be used to probe for a resource’s existence.

Next steps

  • Prompts — the release-confirmation impact card
  • Evaluations — the delete-blocking check
  • Changes — the project-wide “what changed” timeline this feature complements: Changes tells you what happened, Blast Radius tells you what else would be affected before it happens