# Tools agent guide
Built-in contracts, routing, filesystem policy and external bridges.
## Where to look
| Canonical registry, descriptions, schemas and arguments | `capability.rs`, `contract.rs`, `args.rs` |
| Routing/runtime/task ceilings | `dispatch.rs`, `runtime.rs`, `ceiling.rs`, `../tools.rs` |
| File policy, mutation, traversal/cache | `fs.rs`, `workspace.rs`, `fs_cache.rs` |
| Content search | `grep.rs`; `grep/{engine,matcher,reader}.rs` |
| Anchored editing | `hash_edit/`; local guide owns patch contracts |
| Embedded AST search/outline | `ast_grep.rs`, `ast_grep/{search,outline,embedded}.rs` |
| Process execution and inferred file activity | `bash.rs`, `process.rs`, `bash_file_tracking.rs` |
| Public search/page cache/protected fetch | `exa.rs`, `url_fetch.rs` |
| Discovered skills/local images | `skill.rs`, `view_image.rs`, `view_image/requests.rs` |
## Local contracts
- `MVP_TOOL_CAPABILITIES` is canonical registry, not directory inventory. Align ordered names/aliases, arguments, dispatch, descriptions and schemas.
- `ceiling.rs` intersects persisted task permissions with runtime; inspection is deny-by-default in both schemas/dispatch, including aliases/MCP. Text or command matching cannot relax it; trusted hooks/runtime storage lie outside tool-level guarantee.
- Direct and Code Mode exclusions are independent. `ToolRuntime::for_code_mode` changes availability only; retain profile/inspection restrictions and saved per-surface ceilings. No nested `magi_control` or recursive `code_mode`.
- Use each tool's absolute-path settings/filesystem policy, not blanket root-only or string-prefix checks. Mutation locks use canonical paths, lexical normalization when absent, final-symlink rejection, cross-process locks and atomic writes. Parent rechecks after creation reduce races, not an OS sandbox.
- Prose protection assesses prepared before/after content under mutation locks in `fs.rs` and `hash_edit/tool.rs` before writes, not raw patch syntax. Service failure is not a prose defect.
- Provider content stays separate from local `ToolResultDisplay`. Bash inference is bounded/background/local: never promote guesses into touched/changed paths, snapshots or provider content; keep inferred replay labels.
- `read` accepts local files/discovered skills only. Local selectors are per-target; skill bodies/references load fully and reject selectors. Unselected local reads default to 400 lines; retain runtime-only `path` replay alias. Skill references must remain contained.
- AST search/outline/rewrite previews are embedded and read-only, without external CLI/project configs/custom extractors. Retain bounded reads, bundled rules and cooperative deadlines.
- `find` uses shared walker bounds/cancellation. Exact-count/completion flags must reflect partial scans; pagination is not scan resumption.
## Search contracts
- `exa.rs` selects Codex search from dispatch provider/model context through `../providers/openai/codex/web_search.rs`; other search uses environment-only `EXA_API_KEY`. Codex rejects domain/date filters and returns synthesis/citations without page-cache insertion or Exa/MCP fallback.
- Direct URL open uses credential-free protected `url_fetch.rs`. Cached open is bounded/runtime-local/shared across clones and never refetches misses.
- Grep patterns are OR; preserve regex adjustment/literal-fallback counters. Ranked mode groups files/caps primary rows; raw mode sorts path/line and uses one extra primary row for lookahead.
- Pagination counts primary rows, never context. `scan_complete` and `matches_seen_exact` differ; neither can imply full traversal after budget exhaustion. Separate file-prefix truncation from invocation byte exhaustion; unreadable/disappeared files are recoverable outcomes, not successful empty reads. Preserve hidden/ignore/binary filters and bounded context.
Profiling stays with `fs_cache.rs` and `../profiling/profile_harness/` owners.