Skip to content

dependency_cone

Walks the dependency graph outward from one entity or file — upstream (what it depends on), downstream (what depends on it), or both — with a depth limit, so you get a reachability neighborhood instead of the whole graph.

  • When judging the cost of extracting a component into its own package or service.
  • Before upgrading or replacing a dependency, to see everything that would be affected.
  • When you need one entity’s or file’s reachability neighborhood rather than the whole graph.
Name Type Default Description
dep_graph DependencyGraph required Dependency graph to traverse.
target str required An entity FQN or a file path to seed the cone from.
direction str "both" "upstream" (what target depends on), "downstream" (what depends on target), or "both".
max_depth int 3 Maximum hops to walk from the seed (1 = direct neighbors).
max_nodes int | None None Optional per-direction cap on returned nodes — the closest (lowest-distance) nodes are kept first.

The shape varies by branch. Three of the four — resolved cone, no-match, and invalid-direction — are demonstrated directly against click below. The ambiguous-match branch is described from source instead: click’s src/click/ tree is a single flat package with no two files sharing a basename, so it can’t trigger ambiguous/candidate_files on this repo.

Field Type Meaning
target str Echoes the input target (present in every branch).
matched_by "entity" | "file" | None How target resolved: exact entity FQN, exact/suffix file path, or None on no-match, ambiguous-match, and invalid-direction branches.
seed_entities list[str] Sorted FQNs the cone was seeded from — empty when nothing resolved or direction was invalid.
direction / max_depth str / int Echo the inputs (both absent on the invalid-direction branch, which returns error instead).
upstream dict Present when direction is "upstream"/"both" and target resolved: {num_nodes, truncated, nodes, files} — each node in nodes is {fqn, distance, via_relation}; files is the sorted set of file paths those nodes live in.
downstream dict Same shape as upstream, present when direction is "downstream"/"both".
ambiguous / candidate_files / note bool / list[str] / str Present instead of a resolved cone when target’s basename matches more than one distinct file — candidate_files lists them; pass a fuller path to disambiguate. (Behavior from source — not reproducible on a single-package repo like click.)
note str (no ambiguous key) Present alone when nothing at all matched target — a human-readable "No entity or file matched '…'.".
error / valid_directions str / list[str] Present instead of everything else when direction isn’t one of upstream/downstream/both.

Both calls run against the same parse session as the other star-tool pages (dep_graph="fe538dededcc", click’s src/click/ tree). click’s parser only records extends/import edges, so the richest real cones sit in the exception hierarchy.

→ dependency_cone(dep_graph="fe538dededcc", target="click.exceptions.UsageError", direction="both", max_depth=2)
{
"target": "click.exceptions.UsageError",
"matched_by": "entity",
"seed_entities": ["click.exceptions.UsageError"],
"direction": "both",
"max_depth": 2,
"upstream": {
"num_nodes": 1,
"truncated": false,
"nodes": [ { "fqn": "click.exceptions.ClickException", "distance": 1, "via_relation": "extends" } ],
"files": ["click/exceptions.py"]
},
"downstream": {
"num_nodes": 7,
"truncated": false,
"nodes": [
{ "fqn": "click.exceptions.BadArgumentUsage", "distance": 1, "via_relation": "extends" },
{ "fqn": "click.exceptions.BadParameter", "distance": 1, "via_relation": "extends" }
// … 4 more at distance 1
,{ "fqn": "click.exceptions.MissingParameter", "distance": 2, "via_relation": "extends" }
],
"files": ["click/exceptions.py"]
}
}

The second call passes an invalid direction to show the validation-error branch:

→ dependency_cone(dep_graph="fe538dededcc", target="src/click/exceptions.py", direction="sideways")
{
"target": "src/click/exceptions.py",
"error": "Invalid direction 'sideways'.",
"valid_directions": ["upstream", "downstream", "both"]
}
  • A target that matches nothing gets a clean, error-free note, not a crashdependency_cone(target="src/click/nope.py") returned {"matched_by": null, "seed_entities": [], "note": "No entity or file matched 'src/click/nope.py'."}. The only branch that uses error instead is an invalid direction, which has a different key name and payload shape (no seed_entities/direction/max_depth at all) — check matched_by is None for a miss, and don’t treat error and note as interchangeable “something went wrong” markers.
  • max_nodes truncates per direction, keeping the closest nodes. Re-running the same UsageError downstream cone with max_nodes=2 returned only ["BadArgumentUsage", "BadOptionUsage"] (both at distance: 1) with "truncated": true — the distance-2 MissingParameter from the untruncated example was dropped first.
  • Target resolution is intentionally strict about ambiguity: an exact entity FQN wins, then an exact file path, then a path-suffix match — but a bare filename matching files in more than one directory (e.g. two different models.py) returns ambiguous: true with candidate_files rather than silently unioning both files’ cones together. (Behavior from source — not reproducible on a single-package repo like click, whose files all have unique basenames.)
  • dep_graph is resolved from the session store by ID, but the cone result itself isn’t stored back as a new session — no session_id/type pair comes back, so nothing here can be passed as an argument to a later tool call; hold onto the original parse session ID instead.
  • Both upstream and downstream blocks (not the top-level dict) are budget-degraded first when this response is over max_tokens — it carries no top-level graph/architecture key, so it goes through the same generic enforce_budget largest-key-drop path as context_for_task, diff_impact, and api_surface.