<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kun Shen</title>
    <description>The latest articles on DEV Community by Kun Shen (@kun_shen_eedb57cc827955f5).</description>
    <link>https://dev.to/kun_shen_eedb57cc827955f5</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3985949%2F1b0c3bf8-9aab-4dcf-9892-13308c130654.png</url>
      <title>DEV Community: Kun Shen</title>
      <link>https://dev.to/kun_shen_eedb57cc827955f5</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kun_shen_eedb57cc827955f5"/>
    <language>en</language>
    <item>
      <title>How to Build a Crawl Budget That Keeps AI Agents Fast and Predictable</title>
      <dc:creator>Kun Shen</dc:creator>
      <pubDate>Sun, 19 Jul 2026 02:52:52 +0000</pubDate>
      <link>https://dev.to/kun_shen_eedb57cc827955f5/how-to-build-a-crawl-budget-that-keeps-ai-agents-fast-and-predictable-3ge7</link>
      <guid>https://dev.to/kun_shen_eedb57cc827955f5/how-to-build-a-crawl-budget-that-keeps-ai-agents-fast-and-predictable-3ge7</guid>
      <description>&lt;p&gt;AI agents often begin with a deceptively simple web-access loop: take a URL, fetch it, extract text, and pass the result to a model. That loop works in a demo. In production, it can become a source of latency spikes, runaway costs, repeated requests, and inconsistent evidence.&lt;/p&gt;

&lt;p&gt;A crawl budget is the control system that keeps this work predictable. It is more than a request limit. A useful budget decides which pages deserve attention, how much effort each page may consume, and when the agent should stop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the job, not the crawler
&lt;/h2&gt;

&lt;p&gt;The correct budget depends on the agent's task. A monitoring agent may revisit a small set of pages on a schedule. A research agent may explore many domains once. A shopping agent may need current prices but can ignore most navigation pages.&lt;/p&gt;

&lt;p&gt;Write the task as a small contract before choosing limits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what evidence must be collected;&lt;/li&gt;
&lt;li&gt;how fresh the evidence needs to be;&lt;/li&gt;
&lt;li&gt;how many independent sources are required;&lt;/li&gt;
&lt;li&gt;the maximum acceptable latency;&lt;/li&gt;
&lt;li&gt;the maximum cost per completed task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This contract prevents the crawler from treating every discovered URL as equally valuable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give every request an expected value
&lt;/h2&gt;

&lt;p&gt;A URL should enter the queue with a reason. Useful signals include its relationship to the query, the authority of its host, its distance from a known source, its content type, and the chance that it contains new information.&lt;/p&gt;

&lt;p&gt;A simple priority score can combine those signals: priority equals relevance times freshness need times source value, divided by expected cost.&lt;/p&gt;

&lt;p&gt;The formula does not need to be mathematically perfect. Its purpose is to make tradeoffs visible. A product specification linked from a manufacturer's page should normally outrank a tag archive discovered five clicks away.&lt;/p&gt;

&lt;p&gt;Expected cost should include more than bandwidth. JavaScript rendering consumes more time and compute than a direct HTML fetch. A screenshot adds storage and downstream vision cost. Retries also consume the budget, even when they produce no content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use a staged access strategy
&lt;/h2&gt;

&lt;p&gt;The cheapest successful method should win. Start with a normal fetch and examine the result. Escalate to rendering only when the response lacks the content that should be present, relies on client-side navigation, or contains an application shell instead of the requested data.&lt;/p&gt;

&lt;p&gt;Search is often a better first step than blind crawling. A targeted search can identify a few relevant pages before the agent spends budget extracting them. For focused discovery, &lt;a href="https://anycrawler.com/crawler/search/page/" rel="noopener noreferrer"&gt;AnyCrawler's search-page endpoint&lt;/a&gt; is one example of a workflow that combines result discovery with page-level access.&lt;/p&gt;

&lt;p&gt;Screenshots should be deliberate. They are valuable when layout, charts, canvas elements, or visual state are evidence. They should not be the default representation of a text article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate task, host, and page budgets
&lt;/h2&gt;

&lt;p&gt;One global limit is too coarse. Use three layers.&lt;/p&gt;

&lt;p&gt;A task budget limits total requests, rendered pages, bytes, elapsed time, and retries for one user goal. A host budget prevents one domain from consuming the entire task. A page budget caps the work spent on a single stubborn URL.&lt;/p&gt;

&lt;p&gt;Host-level controls also improve politeness. Limit concurrency per host, respect crawl directives, and add delays when a server returns rate-limit or overload responses. Backoff should consume elapsed-time budget so that the agent cannot wait forever.&lt;/p&gt;

&lt;p&gt;Page budgets should define a clear escalation ceiling. For example, allow one fetch, one render attempt if justified, and one retry for a transient failure. Authentication walls, persistent access denials, and repeated empty responses should become explicit outcomes rather than infinite loops.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deduplicate before spending
&lt;/h2&gt;

&lt;p&gt;Agents frequently encounter the same content through tracking parameters, alternate paths, print views, and redirects. Normalize URLs before enqueueing them. Remove known tracking parameters, resolve relative links, and store the final URL after redirects.&lt;/p&gt;

&lt;p&gt;Content fingerprints catch duplicates that URL rules miss. A lightweight hash of normalized main text can prevent the same syndicated article from being processed repeatedly. Keep the source URLs even when content is duplicated; provenance still matters.&lt;/p&gt;

&lt;p&gt;Caching should reflect freshness requirements. Stable documentation can be reused longer than a live price or breaking-news page. Record the retrieval time and cache policy next to the extracted evidence so the agent can decide whether reuse is acceptable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make stopping a first-class decision
&lt;/h2&gt;

&lt;p&gt;A good agent stops because it has enough evidence, not merely because it has exhausted the web. Define completion signals such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the required facts are supported by two independent sources;&lt;/li&gt;
&lt;li&gt;new pages have stopped adding unique claims;&lt;/li&gt;
&lt;li&gt;remaining queue items fall below a value threshold;&lt;/li&gt;
&lt;li&gt;the time or cost reserve is needed for synthesis and verification.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reserve part of the total budget for verification. Discovering ten pages is not useful if no capacity remains to check their claims, dates, and canonical sources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure outcomes, not just requests
&lt;/h2&gt;

&lt;p&gt;Request counts alone cannot reveal whether a budget works. Track useful pages per task, unique evidence items, duplicate rate, render escalation rate, median and tail latency, bytes transferred, and cost per accepted source.&lt;/p&gt;

&lt;p&gt;Also log why pages were skipped or stopped. Reasons such as low relevance, duplicate content, access denied, budget exhausted, and stale cache make later tuning possible.&lt;/p&gt;

&lt;p&gt;Review failures by task type. If research tasks often run out of render budget, the discovery stage may be selecting too many application pages. If monitoring tasks repeatedly fetch unchanged documents, caching or conditional requests need improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical default policy
&lt;/h2&gt;

&lt;p&gt;A reasonable starting policy is conservative: search first, fetch selected pages, render only on evidence of client-side content, and capture screenshots only for visual claims. Cap per-host concurrency, normalize and deduplicate URLs, reserve verification capacity, and stop when evidence coverage is sufficient.&lt;/p&gt;

&lt;p&gt;The exact numbers will change with the product and workload. The structure should remain stable. A crawl budget turns web access from an open-ended exploration into an accountable resource allocation process. That makes agents faster, cheaper, easier to debug, and more respectful of the sites they depend on.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>performance</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>Model an Evidence Chain, Not a Bag of Citations</title>
      <dc:creator>Kun Shen</dc:creator>
      <pubDate>Sat, 18 Jul 2026 04:26:39 +0000</pubDate>
      <link>https://dev.to/kun_shen_eedb57cc827955f5/model-an-evidence-chain-not-a-bag-of-citations-3igh</link>
      <guid>https://dev.to/kun_shen_eedb57cc827955f5/model-an-evidence-chain-not-a-bag-of-citations-3igh</guid>
      <description>&lt;p&gt;AI research products often display citations, but a row of links at the bottom of an answer does not tell you how the answer was built. A citation can be relevant to the topic without supporting the sentence beside it. Several links can repeat the same underlying source. A model can also drop important uncertainty while turning notes into fluent prose.&lt;/p&gt;

&lt;p&gt;The data model has to preserve more than URLs. It should preserve the path from the original question to research queries, retrieved material, evidence grouped by claim, and the final report. We call that path an evidence chain.&lt;/p&gt;

&lt;p&gt;This article focuses on the database and pipeline boundaries that make such a chain reconstructable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The common shortcut: one giant JSON result
&lt;/h2&gt;

&lt;p&gt;The fastest implementation is usually a job table with an input question and one JSON column containing everything else. It works until the product needs to answer operational questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which research query found this source?&lt;/li&gt;
&lt;li&gt;Which source supported this claim?&lt;/li&gt;
&lt;li&gt;Did two citations come from the same domain?&lt;/li&gt;
&lt;li&gt;Was this page reused from an earlier crawl?&lt;/li&gt;
&lt;li&gt;Which model stage changed the wording?&lt;/li&gt;
&lt;li&gt;Can we regenerate the summary without repeating the crawl?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A single blob makes these questions expensive and fragile. Every query becomes a custom JSON traversal, and relationships that should be enforced by keys exist only by convention.&lt;/p&gt;

&lt;p&gt;The better approach is to keep the original run as the parent while giving important artifacts their own records.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Start with a search run
&lt;/h2&gt;

&lt;p&gt;A search run represents one research question and its lifecycle. It owns the status, timestamps, final report, content metadata, and publication decision.&lt;/p&gt;

&lt;p&gt;The run should not pretend that generation is atomic. A real research workflow may expand keywords, search multiple providers, crawl pages, extract page-level facts, aggregate evidence, synthesize a report, classify the content, and calculate an indexability result. Those stages should all reference the same run ID.&lt;/p&gt;

&lt;p&gt;This parent key is what lets an operator reconstruct one execution without correlating timestamps across unrelated log streams.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Store research queries in order
&lt;/h2&gt;

&lt;p&gt;Generated research queries deserve their own ordered records. Order matters because it shows the strategy the system attempted, and stable indices make retries deterministic.&lt;/p&gt;

&lt;p&gt;A minimal query record needs the run ID, a query index, and the query text. You may also want the prompt version that produced it, the provider used, and whether the query was executed or skipped.&lt;/p&gt;

&lt;p&gt;Keeping queries separate makes it possible to evaluate query quality independently from answer quality. If a report misses an important perspective, you can tell whether the gap originated in query generation or later retrieval.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Treat crawled pages as artifacts
&lt;/h2&gt;

&lt;p&gt;Search results and crawled pages are inputs, not yet evidence. A page artifact should record the run, artifact type, query or keyword, URL, retrieval metadata, and the raw or normalized payload needed by later stages.&lt;/p&gt;

&lt;p&gt;That distinction prevents a dangerous shortcut: assuming that every retrieved page supports the answer. Most search results are candidates. Some are duplicates, some only mention the topic, and some contradict the emerging conclusion.&lt;/p&gt;

&lt;p&gt;Page artifacts also create a clean caching boundary. A system can reuse a recent crawl for the same URL while still running fresh evidence extraction for a new question. Retrieval freshness and claim relevance are different concerns and should not share one cache key.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Model evidence around claims
&lt;/h2&gt;

&lt;p&gt;Evidence becomes useful when it is connected to a claim. An evidence record can contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the parent run ID&lt;/li&gt;
&lt;li&gt;a stable evidence index&lt;/li&gt;
&lt;li&gt;the claim it supports or challenges&lt;/li&gt;
&lt;li&gt;the research keyword or query&lt;/li&gt;
&lt;li&gt;source title, summary, and URL&lt;/li&gt;
&lt;li&gt;normalized domain&lt;/li&gt;
&lt;li&gt;an explanation of relevance&lt;/li&gt;
&lt;li&gt;nested source details when several passages support one item&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The claim field is the critical part. It gives reviewers a unit they can inspect. Instead of asking whether a source is “about the topic,” they can ask whether the source supports the specific statement that will appear in the report.&lt;/p&gt;

&lt;p&gt;This structure also enables domain-diversity checks and source counts without parsing rendered Markdown. Quality rules should operate on evidence records before the final page exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Keep model-call provenance beside content provenance
&lt;/h2&gt;

&lt;p&gt;Content provenance explains where facts came from. Model-call provenance explains how the system transformed those facts. Both are required for reproducibility.&lt;/p&gt;

&lt;p&gt;For each stage, retain request messages, structured inputs, the raw provider response, parsed output, model and reasoning configuration, token usage, latency, prompt version, and errors. Link every call to the same run.&lt;/p&gt;

&lt;p&gt;With that relationship, a reviewer can move in both directions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;from a sentence in the report to its claim and sources&lt;/li&gt;
&lt;li&gt;from a suspicious source to the extraction and synthesis calls that consumed it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is much more actionable than a generic “generated by AI” label.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Save the final report, but do not make it the source of truth
&lt;/h2&gt;

&lt;p&gt;The final report is a presentation artifact. It may be Markdown or HTML, and it may include inline links for readers. But source counts, domain counts, confidence, and evidence sufficiency should come from structured data, not from scraping the report after generation.&lt;/p&gt;

&lt;p&gt;That separation has a practical benefit: presentation can change without destroying provenance. You can redesign citation components, generate mobile summaries, or expose an API while keeping the same underlying evidence relationships.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Make insufficiency a valid outcome
&lt;/h2&gt;

&lt;p&gt;An evidence chain should be able to end without a publishable answer. If retrieval produces too few sources, domains are not independent, or the evidence conflicts, the run can complete with an insufficiency flag and clear reasons.&lt;/p&gt;

&lt;p&gt;This is not a pipeline failure. It is a research result. Treating insufficiency as data prevents the system from filling gaps with more confident prose simply to satisfy a success state.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Expose enough of the chain to readers
&lt;/h2&gt;

&lt;p&gt;Internal logs can contain sensitive or operational details, so they should not be dumped into a public page. Readers still benefit from a carefully selected public surface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;visible source links&lt;/li&gt;
&lt;li&gt;source titles and domains&lt;/li&gt;
&lt;li&gt;claim-oriented evidence groups&lt;/li&gt;
&lt;li&gt;correction and attribution channels&lt;/li&gt;
&lt;li&gt;methodology and editorial policy pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The public &lt;a href="https://omniracle.com/methodology" rel="noopener noreferrer"&gt;Omniracle methodology&lt;/a&gt; describes how signal discovery, research, evidence, model provenance, and publication gates fit together. The &lt;a href="https://omniracle.com/recommended" rel="noopener noreferrer"&gt;recommended reports&lt;/a&gt; show the reader-facing side of that architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  A useful mental model
&lt;/h2&gt;

&lt;p&gt;Think of the pipeline as a directed chain:&lt;/p&gt;

&lt;p&gt;question → research queries → page artifacts → claim evidence → synthesis calls → final report → publication decision&lt;/p&gt;

&lt;p&gt;Each arrow should be represented by a durable relationship, not inferred later from similar text. When a result is challenged, the system can then answer the most important engineering question: not merely “Which links were shown?” but “How did this claim travel from source material into the published answer?”&lt;/p&gt;

&lt;p&gt;That is the difference between citation decoration and an auditable research system.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>database</category>
      <category>dataengineering</category>
    </item>
    <item>
      <title>Building Reliable Web Access for AI Agents: Search, Crawl, Markdown, and Screenshots</title>
      <dc:creator>Kun Shen</dc:creator>
      <pubDate>Mon, 15 Jun 2026 16:54:41 +0000</pubDate>
      <link>https://dev.to/kun_shen_eedb57cc827955f5/building-reliable-web-access-for-ai-agents-search-crawl-markdown-and-screenshots-e9e</link>
      <guid>https://dev.to/kun_shen_eedb57cc827955f5/building-reliable-web-access-for-ai-agents-search-crawl-markdown-and-screenshots-e9e</guid>
      <description>&lt;p&gt;AI agents are only as useful as the context they can reach. For many product, research, support, and competitive-intelligence workflows, that context lives on public websites: documentation pages, changelogs, pricing pages, articles, search results, screenshots, and long-tail reference content.&lt;/p&gt;

&lt;p&gt;The hard part is not simply "scraping a page." The hard part is giving an agent a repeatable web access layer that can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;search for candidate sources,&lt;/li&gt;
&lt;li&gt;fetch static pages cheaply,&lt;/li&gt;
&lt;li&gt;render JavaScript-heavy pages when needed,&lt;/li&gt;
&lt;li&gt;convert pages into clean markdown,&lt;/li&gt;
&lt;li&gt;capture screenshot evidence,&lt;/li&gt;
&lt;li&gt;retry safely when upstream sites are slow,&lt;/li&gt;
&lt;li&gt;and avoid flooding the model context with irrelevant HTML.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where a web scraping API or crawler API becomes more useful than ad hoc browser scripts.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical pattern for agent web access
&lt;/h2&gt;

&lt;p&gt;For most AI agent workflows, I like to split web access into four steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Search first, crawl second
&lt;/h3&gt;

&lt;p&gt;Agents often do better when they first discover likely sources instead of starting with one URL. A search API for AI agents can return public web, news, image, video, or scholar results. The agent can then choose the highest-signal pages to read.&lt;/p&gt;

&lt;p&gt;This reduces unnecessary crawling and gives the model a better source set.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Use fetch before render
&lt;/h3&gt;

&lt;p&gt;Many pages do not need a headless browser. Documentation, blog posts, landing pages, legal pages, and static HTML often contain the useful content in the initial response.&lt;/p&gt;

&lt;p&gt;For those pages, a fetch-based web data extraction API is usually faster, cheaper, and more reliable.&lt;/p&gt;

&lt;p&gt;Use browser rendering only when the page depends on client-side JavaScript, hydration, or late network calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Convert pages to markdown
&lt;/h3&gt;

&lt;p&gt;Raw HTML is noisy. Agents usually need a compact representation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;page title,&lt;/li&gt;
&lt;li&gt;main content,&lt;/li&gt;
&lt;li&gt;links,&lt;/li&gt;
&lt;li&gt;metadata,&lt;/li&gt;
&lt;li&gt;selected media,&lt;/li&gt;
&lt;li&gt;and readable markdown.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Website to markdown conversion is a simple change that often improves answer quality because the model sees content instead of layout scaffolding.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Capture screenshots when trust matters
&lt;/h3&gt;

&lt;p&gt;Text extraction is enough for many tasks, but not all of them. When an agent is checking visual layout, pricing evidence, legal copy, product UI, or compliance-sensitive content, a screenshot API gives a durable record of what the page looked like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where AnyCrawler fits
&lt;/h2&gt;

&lt;p&gt;I have been testing &lt;a href="https://anycrawler.com" rel="noopener noreferrer"&gt;AnyCrawler&lt;/a&gt; as an agent-facing web access layer. It combines public search, page crawling, markdown extraction, browser rendering, and screenshots behind API endpoints that are easier for agents to call than a full browser automation stack.&lt;/p&gt;

&lt;p&gt;The useful part is the routing model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;a href="https://anycrawler.com/crawler/page/fetch" rel="noopener noreferrer"&gt;fetch crawling&lt;/a&gt; for static or content-first pages,&lt;/li&gt;
&lt;li&gt;use &lt;a href="https://anycrawler.com/crawler/page/render" rel="noopener noreferrer"&gt;render crawling&lt;/a&gt; for JavaScript-heavy pages,&lt;/li&gt;
&lt;li&gt;use &lt;a href="https://anycrawler.com/crawler/screenshot" rel="noopener noreferrer"&gt;screenshots&lt;/a&gt; when visual evidence matters,&lt;/li&gt;
&lt;li&gt;and use &lt;a href="https://anycrawler.com/crawler/search/page" rel="noopener noreferrer"&gt;search&lt;/a&gt; before crawling when the source URL is not already known.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is also an open skill package for agent runtimes here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AnyCrawler-com/AnyCrawler-Skill" rel="noopener noreferrer"&gt;https://github.com/AnyCrawler-com/AnyCrawler-Skill&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Design advice
&lt;/h2&gt;

&lt;p&gt;If you are adding web access to an AI agent, avoid making the browser the first tool for every task. A better default is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search if the source is unknown.&lt;/li&gt;
&lt;li&gt;Fetch the page if content is likely available in HTML.&lt;/li&gt;
&lt;li&gt;Render only when fetch is incomplete.&lt;/li&gt;
&lt;li&gt;Convert the result to markdown.&lt;/li&gt;
&lt;li&gt;Capture screenshots only when the task needs visual proof.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That structure keeps workflows faster, less expensive, and easier to debug.&lt;/p&gt;

</description>
      <category>webscraping</category>
    </item>
  </channel>
</rss>
