aethexDocs

Reference links

Attach a URL to an agent and Aethex crawls it into the agent's knowledge base. Nothing is fetched during a call.

How it works

You attach one or more URLs to an agent. A background job fetches each page, converts it to clean markdown, splits it into chunks, embeds them, and files each page as an ordinary knowledge-base document. From there it is the same retrieval as an uploaded PDF: a local search of a few tens of milliseconds, with nothing fetched while the call is running. A link can be a single page, or a whole site: in `site` mode the crawler follows the page's internal links, bounded by the limits below.

THE FIRST PASSattachone or more URLscrawlextract + embedreviewnothing servedin serviceanswers callsapproverejectedchunks removedexcludeEVERY PASS AFTERre-crawlfixed intervalunchanged, nothing happenschanged, replaced silentlycollapsed, held backheld backold page servedin serviceshort page winsacceptOnly the labelled arrows need a person. Everything else runs on its own.

Attaching links

Send a list, not one URL at a time. `crawl_mode` is per link, because a documentation root is worth crawling as a `site` while a pricing page is not. The request returns immediately with each link `queued`: a fifty-page crawl with embedding does not fit inside an HTTP request.

attach_links.sh
bash
curl -X POST "$BASE_URL/agents/$AGENT_ID/reference-links" \
  -H "X-API-Key: $AETHEX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "links": [
      { "url": "https://docs.example.com/", "crawl_mode": "site" },
      { "url": "https://example.com/pricing", "crawl_mode": "page" }
    ]
  }'
Note
All or nothing. One malformed URL rejects the whole request with a message naming it, rather than creating the others and leaving you to work out which ones landed. Two spellings of the same page, with and without tracking parameters, count as one link and are refused as a duplicate.

Nothing is served until you approve it

A crawl does not put anything in front of your callers. Every page it stores waits in `pending_review` until you approve the link, because a bad scrape that lands silently poisons all future calls. The preview sorts anomalies first rather than by crawl order. A held candidate, then anything awaiting review, and within each group the shortest extraction first, since a page that came back nearly empty is the likeliest bad scrape. Approving takes the whole link, minus the pages you exclude; an excluded page is remembered as rejected and loses its chunks, so the index carries nothing that will never be served.

review_and_approve.sh
bash
# What the crawl found, anomalies first.
curl "$BASE_URL/agents/$AGENT_ID/reference-links/$LINK_ID/pages" \
  -H "X-API-Key: $AETHEX_API_KEY"

# Put them into service, minus the ones you do not want.
curl -X POST "$BASE_URL/agents/$AGENT_ID/reference-links/$LINK_ID/approve" \
  -H "X-API-Key: $AETHEX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "exclude": ["doc-uuid-of-a-page-you-reject"] }'

Re-crawling

Every link is re-read on a fixed interval so a page that changes does not go stale. There is no per-link setting: the interval is the same for every link, which means a link cannot be pinned to never re-crawl. A pass that finds the page unchanged does nothing at all: it does not re-embed, and it does not ask you to approve anything again.

Note
A page already in service never regresses. If a re-crawl finds the page changed, it replaces it silently and stays in service. If it finds the page unreachable, or renders no extractable text, it changes nothing and keeps serving what it had. Stale content beats a hole in the agent's knowledge, provided the hole is visible on the link.

When a page collapses

One case gets neither treatment: a re-crawl that comes back with a fraction of the text it had before. That is what a broken template or a site migration looks like, and replacing good content with it would be worse than doing nothing. So the page keeps serving what it had, and the new extraction is held aside as a candidate. The preview then shows both sides: the size before, the size now, and the candidate's own title, so you can judge which one is the real page.

GET .../pages (one entry)
json
{
  "id": "doc-uuid",
  "source_url": "https://docs.example.com/pricing",
  "status": "completed",
  "size_bytes": 7178,
  "chunk_count": 4,
  "candidate": {
    "at": "2026-08-31T12:19:22Z",
    "title": "Pricing",
    "size": 501,
    "previous_size": 7178
  }
}
accept_candidate.sh
bash
# Accept it, and the shorter version takes over without the page
# ever leaving service.
curl -X POST \
  "$BASE_URL/agents/$AGENT_ID/reference-links/$LINK_ID/pages/$DOC_ID/accept-candidate" \
  -H "X-API-Key: $AETHEX_API_KEY"
Heads up
There is no way to dismiss a candidate, only to accept it. The hold says the source is currently serving a page that lost most of its text, which stays true until the site changes, and clears itself when it does, because the next pass sees new content and replaces the page outright. Accepting publishes the shorter version and re-embeds it, and the page never leaves service while that happens.

Reading a link's state

`crawl_state` answers one question only: did the crawl work. It is written by a crawl and nothing else, so every value it can hold is settled the moment a pass ends.

queued

Attached, waiting for its first pass.

crawling

A pass is running right now.

ready

The crawl reached every page it meant to.

partial

The crawl lost something: it stopped at the page limit or its time budget, or some pages failed. `last_crawl_error_detail` names which.

failed

The crawl brought back nothing. `last_crawl_error_code` says why.

Heads up
If you are building a UI, colour a row on pages.flagged > 0, not on crawl_state. The flagged count is what says a human needs to look, and it is recomputed on every read, so it drops to zero the instant you accept a candidate, without waiting for the next crawl. A page whose extraction collapsed leaves the link ready, because the crawl itself worked.

Why a link failed

A failure on a discovered page does not stop the crawl: it is recorded and the pass continues, and `last_crawl_error_detail` summarises what went wrong. A failure on the URL you attached fails the link, and `last_crawl_error_code` carries one of the following.

CodeWhat happenedWhat you can do
unreachableDNS failed, the connection was refused, or the redirects never resolved to a page we can fetch.Check the URL resolves and answers from outside your network.
timeoutThe page did not answer inside its budget.Retry later, or attach a page that responds faster.
http_4xxThe server answered 4xx. Most often the page does not exist.Fix the URL.
http_5xxThe server answered 5xx.The site is broken or overloaded; wait and retry.
paywalled401, 402 or 403: there is content here we are not allowed to read.Attach a publicly readable page instead.
js_onlyThe fetch succeeded but the HTML carried no readable text: the page renders in the browser, so what arrived is a shell.Attach a URL that serves HTML. On a portal root, `site` mode often reaches the real pages one click in.
robots_disallowed`robots.txt` forbids this path for our crawler.Nothing: we respect it. Attach a different URL.
too_largeThe page body passed the size ceiling while being read.Attach a narrower page.
blocked_hostThe URL resolved to a private, internal or cloud-metadata address.Nothing: refused on security grounds. Attach a public URL.
internal_errorThe crawl job itself failed. This one is ours, not the site's.Nothing: the pass is rescheduled automatically.

Limits

Ten links per agent. A `site` crawl reads up to 50 pages, three levels deep, and gives up after ten minutes. A single page is read up to 5 MB. The crawler identifies itself, honours `robots.txt` including `Crawl-delay`, and makes one request at a time per host with a pause between them. It is reading someone else's site, not stress-testing it. These are the same for every account and are not configurable.

Next

Reference links and uploaded files land in the same place. See the knowledge base for what happens to a document once it is in service, and how retrieval uses it.