Skip to content

Commit faf3679

Browse files
HumanBean17claude
andcommitted
add agent tool selection heuristics, experimental branch targeting
- Add "Agent tool selection: trace vs neighbors" section with: - Decision table mapping question intents to trace/neighbors - Reasoning preamble update for the trace Q-class - Hint system updates: fan-out, loop escalation, drill-down, budget hit, cross-service boundary hints - Skill decision tree rows for trace use cases - Mark proposal as experimental, target branch is `experimental` not `master` - Add "Experimental validation" section with quantitative criteria (multi-hop accuracy, tool call reduction, no regression, latency) and qualitative criteria (agent tool selection, pruning quality) - Add graduation process and rollback plan - Update Appendix A to acknowledge the v2 decision was correct and trace is an experiment to validate the hypothesis Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 667ac22 commit faf3679

1 file changed

Lines changed: 105 additions & 1 deletion

File tree

propose/active/TRACE-TOOL-PROPOSE.md

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# TRACE-TOOL -- Multi-hop navigation shortcut
22

3-
**Status**: active
3+
**Status**: active (experimental)
4+
**Target branch**: `experimental` — not `master`. `trace` is an experiment; it ships on a dedicated branch and is not merged to `master` until validated in production.
45
**Author**: Dmitry + Computer
56
**Date**: 2026-05-25
67

@@ -10,6 +11,8 @@
1011

1112
The v2 design locked in `neighbors` as the sole multi-hop primitive, requiring the agent to call it in a loop. In practice, agents drown during tracing: fan-out explosion (each CALLS hop produces 5-10 edges), no visited set (LLMs revisit nodes, follow cycles), low-signal edges dominate (getters, logging, framework plumbing), and context is consumed on traversal mechanics rather than understanding. The proposed `trace` tool is a **batched navigation shortcut** -- it does multi-hop BFS server-side in one call and returns paths/structure, not answers. The agent still interprets results. It is a sixth tool on the MCP surface, composing with the existing five.
1213

14+
**This is an experiment.** The tool ships on the `experimental` branch, not `master`. It will be merged to `master` only after validation: agents using `trace` must produce measurably better results on multi-hop questions than agents using `neighbors` loops, with no regression on single-hop queries. The validation criteria are defined in the "Experimental validation" section below.
15+
1316
## Problem Statement
1417

1518
### The drowning problem
@@ -185,6 +188,69 @@ Cross-service traversal is implicit: when `HTTP_CALLS` or `ASYNC_CALLS` is in `e
185188

186189
The `nodes` dict in `TraceOutput` contains lightweight `NodeRef` objects (id, kind, fqn, role). For deeper inspection, the agent calls `describe(id)` on specific nodes. This preserves the GPS metaphor: `trace` maps the route, `describe` and `neighbors` provide street-level detail.
187190

191+
### Agent tool selection: `trace` vs `neighbors`
192+
193+
When the agent has a node ID and needs to navigate, it chooses between `neighbors` (one-hop) and `trace` (multi-hop with pruning). The decision is driven by **question intent**, not hop count. The following heuristics must be reflected in `_INSTRUCTIONS`, `skills/explore-codebase/SKILL.md`, and `mcp_hints.py`.
194+
195+
#### Decision table
196+
197+
| Agent intent | Tool | Rationale |
198+
|---|---|---|
199+
| "What does M call?" / "Who calls M?" | `neighbors` | 1-hop adjacency, agent wants full unfiltered result |
200+
| "What implements T?" / "Where is T injected?" | `neighbors` | 1-hop structural exploration, single edge type |
201+
| "List all routes/controllers/clients" | `find` + `neighbors` | Enumerate + one-hop detail |
202+
| "What happens when POST /api/orders is called?" | `trace` | Multi-hop path question: route -> handler -> service -> repository |
203+
| "Impact of changing X" | `trace` | Multi-hop breadth-first, needs pruning to stay focused |
204+
| "Trace from controller to database" | `trace` | Named start/end implies multi-hop path |
205+
| "What crosses service boundaries from X?" | `trace` | Cross-service is `trace`'s highest-value feature |
206+
| "What's the call chain from A to B?" | `trace` | Multi-hop path with named endpoints |
207+
| After `trace` returns pruned result | `neighbors` on specific nodes | Drill into edges that `trace` collapsed or pruned |
208+
| After `neighbors` returns high fan-out (>8 CALLS edges) | `trace` with `prune_roles` + `fan_out_cap` | Switch strategy when `neighbors` result is too noisy |
209+
| Agent is 3+ hops into a `neighbors` loop | `trace` from original seed | Escalation: stop drowning, batch the remaining traversal |
210+
211+
#### Reasoning preamble update
212+
213+
The current forced reasoning preamble in `SKILL.md` is:
214+
```
215+
Q-class: <semantic | structured | inspect | walk>
216+
Pick: <search|find|describe|neighbors|resolve> Why: <≤8 words>
217+
```
218+
219+
With `trace`, the preamble becomes:
220+
```
221+
Q-class: <semantic | structured | inspect | walk | trace>
222+
Pick: <search|find|describe|neighbors|trace|resolve> Why: <≤8 words>
223+
```
224+
225+
The `trace` Q-class applies when: (a) the question implies a path or chain, (b) the agent needs to cross a service boundary, or (c) a `neighbors` loop has exceeded 2 hops without converging.
226+
227+
#### Hint system updates (`mcp_hints.py`)
228+
229+
PR-TRACE-3 must add the following `trace`-aware hints:
230+
231+
1. **Neighbors high fan-out hint**: When `neighbors` returns >8 CALLS edges for a single node, emit a hint: `"High fan-out (N CALLS edges). Consider trace(id, 'out', ['CALLS'], prune_roles=['DTO','EXCEPTION','UTILITY'], fan_out_cap=5) for a pruned multi-hop view."`
232+
233+
2. **Neighbors loop escalation hint**: When the same session issues 3+ consecutive `neighbors` calls with the same `edge_types` and direction, emit: `"You've issued N neighbors calls with the same edge type. Consider trace(seed_id, direction, edge_types, max_depth=4) to batch the traversal."` (This requires session-level call tracking, which the MCP server does not currently have. This may need to be a client-side hint in the skill rather than server-side.)
234+
235+
3. **Trace result drill-down hint**: When `trace` returns edges with `collapsed=True` or `stats` shows pruning fired, emit: `"trace pruned N edges. Use neighbors(id, direction, edge_types) on specific nodes for full detail."`
236+
237+
4. **Trace budget hit hint**: When `stats.budget_hit=True`, emit: `"trace hit the node discovery budget (N nodes). Results are partial. Increase max_depth or add prune_roles and re-run."`
238+
239+
5. **Cross-service boundary hint**: When `trace` discovers cross-service edges, emit: `"Cross-service boundary detected. Use describe(route_id) on downstream routes for handler details."`
240+
241+
#### Skill decision tree update
242+
243+
The decision tree in `skills/explore-codebase/SKILL.md` must be updated to include `trace` rows:
244+
245+
| User asks... | First step | Typical follow-up |
246+
|---|---|---|
247+
| "What happens when route R is called?" | `find(kind="route")` then `trace(route_id, "out", ["EXPOSES","CALLS"], max_depth=4)` | `describe` on key nodes |
248+
| "Impact of changing method M" | `resolve` / `find` then `trace(id, "in", ["CALLS","OVERRIDES"], max_depth=3)` | `describe` on callers |
249+
| "Trace from X to database" | `trace(id, "out", ["CALLS"], max_depth=4, prune_roles=["DTO","EXCEPTION"])` | `neighbors` for pruned detail |
250+
| "What calls this across services?" | `trace(id, "out", ["CALLS","HTTP_CALLS","ASYNC_CALLS"], max_depth=5)` | `describe` on downstream routes |
251+
252+
The existing `neighbors` rows remain unchanged. `trace` rows are additive — they cover the cases where the current table says "loop neighbors" or "no magic tool."
253+
188254
### Depth and budget control
189255

190256
- `max_depth` defaults to **3** and is clamped to 1..5.
@@ -322,6 +388,40 @@ These questions were resolved during review (PR #234). Deferred items are tracke
322388
- **#240** — trace tool: v2 enhancements (bidirectional traversal, richer collapse_trivial heuristic, configurable path ranking, configurable fan_out_cap ranking)
323389
- **#241** — trace tool: CLI integration and legacy method deprecation
324390

391+
## Experimental validation
392+
393+
`trace` ships on the `experimental` branch. It is merged to `master` only when the following criteria are met:
394+
395+
### Quantitative criteria
396+
397+
1. **Multi-hop accuracy**: For a set of 10 multi-hop questions (3+ hops, mixed intra/cross-service), agents using `trace` produce correct answers in ≥80% of cases. The baseline is agents using `neighbors` loops on the same questions (currently ~40% based on production observation).
398+
399+
2. **Tool call reduction**: `trace` reduces tool calls by ≥50% for multi-hop questions compared to `neighbors` loops (measured on the same question set).
400+
401+
3. **No regression on single-hop**: For a set of 10 single-hop questions where agents currently use `neighbors`, introducing `trace` as an option does not degrade accuracy or increase tool calls. Agents must still pick `neighbors` for single-hop questions.
402+
403+
4. **Latency**: `trace` call latency is under 500ms for depth 3 on the `bank-chat-system` fixture, and under 2s for depth 5 on a large codebase (10K+ methods).
404+
405+
### Qualitative criteria
406+
407+
5. **Agent tool selection**: In ≥70% of multi-hop questions, the agent picks `trace` over a `neighbors` loop without manual prompting. This validates that the `_INSTRUCTIONS` and skill guidance are effective.
408+
409+
6. **Pruning quality**: In post-trace inspection, ≥80% of pruned edges (those cut by `prune_roles`, `fan_out_cap`, or `collapse_trivial`) are genuinely low-signal. Measured by human review of a random sample.
410+
411+
### Graduation process
412+
413+
1. All PR-TRACE PRs merge to `experimental`.
414+
2. Run validation suite against `tests/bank-chat-system` and at least one real codebase.
415+
3. If all criteria pass, open a PR to merge `experimental` into `master`.
416+
4. If criteria fail, iterate on pruning heuristics and agent guidance, then re-run.
417+
418+
### Rollback plan
419+
420+
If `trace` causes regressions in production after merging to `master`:
421+
- Remove the `trace` tool registration from `server.py` (one-line revert).
422+
- `mcp_trace.py` remains in the tree but is no longer reachable.
423+
- No re-index required.
424+
325425
## Out of scope
326426

327427
- **Answer engine.** `trace` returns paths and structure. It does not synthesize natural-language answers or recommendations.
@@ -334,6 +434,8 @@ These questions were resolved during review (PR #234). Deferred items are tracke
334434

335435
## Sequencing / Follow-ups
336436

437+
All PR-TRACE PRs target the `experimental` branch. They do not merge to `master` until the experimental validation criteria are met.
438+
337439
### PR-TRACE-1a -- `mcp_trace.py` core BFS engine
338440

339441
- Implement `TraceOutput`, `TraceEdge`, `TracePath`, `TraceStats` models.
@@ -391,6 +493,8 @@ The key difference from the rejected v1 `trace_flow` tool: `trace_flow` was a **
391493

392494
What changed between v2 design (2026-05-07) and now (2026-05-25): production experience with the 5-tool surface on real microservice codebases showed that the `neighbors` loop approach works for 80% of queries (1-2 hop) but degrades severely for the remaining 20% (3+ hops, cross-service). The agent drowning pattern is consistent and reproducible. A batched shortcut that preserves the GPS metaphor is the right fix.
393495

496+
The v2 "no trace tools" decision was made with good reason. `trace` ships as an **experiment** on the `experimental` branch to validate the hypothesis that server-side pruning helps agents without violating the GPS contract. If the experiment fails, the rollback is trivial: remove one tool registration, no re-index.
497+
394498
## Appendix B -- Comparison with `neighbors` loop
395499

396500
| Aspect | `neighbors` loop | `trace` |

0 commit comments

Comments
 (0)