# Journey 17 — Beyond Coding: Web & Research

> Not every agent task is code. You want the agent to read a changelog, pull an
> API spec, summarise an RFC, or extract the claims from a blog post or a video —
> without pasting raw HTML into the context window. This journey covers
> `ctx_url_read`: one tool that turns a URL, PDF, or YouTube video into
> **compressed, citation-backed context**.

Source files referenced here:
- `rust/src/tools/registered/ctx_url_read.rs` — the MCP tool (`CtxUrlReadTool`), arg parsing + clamps
- `rust/src/core/web/mod.rs` — `read_url`, `ReadMode`, `ReadOptions`, `DEFAULT_MAX_TOKENS`/`DEFAULT_MAX_ITEMS`
- `rust/src/core/web/url_guard.rs` — SSRF guard (scheme + private/loopback/link-local block)
- `rust/src/core/web/fetch.rs` — bounded, redirect-revalidated HTTP fetch (`DEFAULT_TIMEOUT_SECS`)
- `rust/src/core/web/html_to_text.rs` — HTML → clean Markdown
- `rust/src/core/web/pdf.rs` — remote PDF → text
- `rust/src/core/web/youtube.rs` — video URL → transcript
- `rust/src/core/web/distill.rs` — research-compression modes
- `rust/src/core/web/citation.rs` — source attribution (`Citation`)
- `rust/src/core/evidence.rs` — `Claim` (confidence + source) for `facts`/`quotes`

---

## 0. The principle

> `ctx_url_read` is the web counterpart of `ctx_read`: one tool call, one token
> budget, boilerplate stripped, the source preserved for citation. Nothing is
> fetched unless you pass a URL, and only `http`/`https` URLs that survive the
> SSRF guard are ever requested.

---

## 1. The pipeline

`read_url` (`core/web/mod.rs`) is the single entry point; the MCP tool is a thin
wrapper over it. The flow:

1. **`url_guard`** validates the URL and blocks SSRF targets.
2. **`fetch`** downloads it (bounded, manual-redirect, SSRF-revalidated) — or
   **`youtube`** pulls a transcript for video URLs.
3. **`html_to_text`** renders HTML to clean Markdown (and **`pdf`** converts a
   remote PDF to text).
4. **`distill`** applies the requested research-compression mode.
5. **`citation`** attaches source attribution.

---

## 2. The tool surface

`CtxUrlReadTool::handle` (`ctx_url_read.rs`) parses the arguments, clamps them,
and calls `web::read_url`.

| Argument | Type | Default | Clamp | Code |
|----------|------|---------|-------|------|
| `url` | string | — (required) | — | `get_str(args, "url")` |
| `mode` | string | `auto` | enum | `ReadMode::parse` |
| `query` | string | — | — | `get_str(args, "query")` |
| `max_tokens` | integer | `6000` | `200..=50_000` | `DEFAULT_MAX_TOKENS` |
| `max_items` | integer | `12` | `1..=100` | `DEFAULT_MAX_ITEMS` |
| `timeout_secs` | integer | `20` | `1..=60` | `fetch::DEFAULT_TIMEOUT_SECS` |

---

## 3. Distillation modes

`ReadMode` (`core/web/mod.rs`) selects how fetched content is distilled before it
is returned. `distill.rs` implements the extractive, relevance-ranked logic.

| Mode | What you get | Code path |
|------|--------------|-----------|
| `auto` | Markdown for pages, transcript for videos (default) | `ReadMode::Auto` |
| `markdown` | Clean Markdown of the main content | `html_to_text` |
| `text` | Plain text (Markdown decorations stripped) | `distill` |
| `links` | Extracted hyperlinks (max 100) | `MAX_LINKS` |
| `facts` | Sentences carrying factual signals, as `Claim`s | `distill` + `evidence::Claim` |
| `quotes` | Central / query-relevant sentences as evidence | `distill` + `evidence::Claim` |
| `transcript` | De-duplicated, filler-stripped transcript | `youtube` + `transcript_compact` |

`mode` parsing accepts a few aliases: `md`→markdown, `plain`→text, `summary`→transcript.

```bash
# Auto mode — Markdown for a page
ctx_url_read url="https://example.com/post"

# A remote PDF as text within a 3000-token budget
ctx_url_read url="https://example.com/paper.pdf" mode="text" max_tokens=3000

# A YouTube transcript
ctx_url_read url="https://youtu.be/VIDEO" mode="transcript"
```

---

## 4. Citations & evidence

The `facts` and `quotes` modes do not just summarise: each returned item is a
`Claim` (`core/evidence.rs`) carrying a **confidence score** and the **source
URL** it came from (`citation.rs`). That makes web research auditable — the agent
can attribute every statement, and you can verify it later. A `query` boosts
relevance so extraction focuses on the part of the page you care about.

```bash
ctx_url_read url="https://example.com/spec" mode="facts" query="rate limits and quotas"
```

---

## 5. Research compression

A single documentation page can blow a context window. `read_url` distils the
fetched content down to `max_tokens` (default `DEFAULT_MAX_TOKENS` = 6000) using
extractive, relevance-ranked compression, and caps `facts`/`quotes` at
`max_items` (default `DEFAULT_MAX_ITEMS` = 12). The tool then appends the usual
savings line (`append_savings`) so the token budget is visible.

---

## 6. Safety — the SSRF guard

`url_guard.rs` enforces, before any request and again after each redirect in
`fetch.rs`:

- only `http` / `https` schemes are allowed;
- requests to **private, loopback and link-local** addresses are blocked.

So an agent cannot be steered into probing your internal network. Fetches are
bounded in size and honour `timeout_secs` (default 20, max 60).

---

## 7. Where it fits

`ctx_url_read` ships with the binary and is registered in
`rust/src/server/registry.rs`, so it is exposed automatically wherever lean-ctx
runs as an MCP server — no extra configuration. Pair it with
`ctx_knowledge` to remember what you learned, and it becomes a durable research
loop that survives the session.
