Help Wren Navigate the Repository
Explore how to enable AI coding agents like Wren to effectively and safely navigate unfamiliar repositories by implementing structured discovery steps: listing files, searching content, and reading specific code excerpts. Understand policies for stable ordering, output limits, and security checks to maintain trustworthy, reproducible evidence gathering. This lesson helps you build robust discovery contracts, refine tool scopes, and improve the reliability of cross-session coding agent operations.
We'll cover the following...
- What are we building in this lesson?
- Why isn’t read enough?
- What makes repository output trustworthy?
- Where should the discovery rules live?
- Why does one path need two checks?
- How does list avoid becoming another context dump?
- What should search return?
- What do Pi and DeepSeek Harness teach us here?
- When does a tool actually exist?
- Can you make the discovery contract pass?
- Can you map discovery from task to evidence?
- What can you add to your own harness today?
Wren could read a file only when the model already knew its path. That limitation surfaced in CLIN-584. The ticket asked the agent to determine why replacement appointments bypassed the overlap check. The model assumed the relevant file was src/availability.ts, received ENOENT, then attempted to use a permitted shell command:
> bash({"command":"ls -R"})> ok .: README.md node_modules src test ... 13,842 more lines> read({"path":"src/availability.ts"})> failed: ENOENT
The right implementation was availability.js at the repository root. The agent had permission to read it and no reliable way to discover it. Its fallback returned so much directory noise that the useful filename disappeared inside the result.
This is a reach failure. The agent can inspect known files with read, but it cannot discover which files are relevant. Broader shell access would give the agent more ways to search the filesystem, but it would not make discovery bounded, repeatable, or safe to expose in the model context. Wren needs dedicated discovery tools with explicit scope and output constraints.
What are we building in this lesson?
Picture a learner entering an unfamiliar library. They should not pull every book from every shelf. They need three moves:
Look at the catalogue to learn which books exist.
Search the catalogue for a topic and get a shelf address.
Open one book at that address.
Wren will gain the repository version of those moves:
Questions that Agent Is Thinking | Tool | Small Result |
“What files might matter?” |
| Sorted file paths |
“Which file mentions this rule?” |
| Path, line number, matching line |
“What does that code say?” |
| A bounded file excerpt |
The tools form a funnel. Each answer makes the next request narrower. If you remember only one picture, remember list -> search -> read.
Why isn’t read enough?
Because read begins after the file has been identified.
A model can call read("availability.js") only when the file path is available in the task, conversation, or an earlier tool result. Without a known path, the model must infer one. A correct inference may work in a controlled demo. In an unfamiliar repository, incorrect path inference wastes tool calls and often targets the wrong file.
Repository discovery has three separate questions:
What exists?
listreturns a small, ordered map of candidate files.
Where does this fact appear?
searchreturns paths, line numbers, and matching lines.
What is the evidence around it?
readreturns file contents within a declared byte budget.
Using one tool for all three operations weakens the tool contract. Recursive listing can add excessive output to the model context. Reading inferred paths wastes tool calls when those paths are incorrect. Search results without line references force the agent to locate the same match again before reading it.
Select the four discovery stages below in order. Observe how the output narrows from an initial clue to a focused code ...