Trust
How Krawl handles citation, verification, failure modes, refunds, and audit — the methodology page an autonomous agent's owner should read before wiring Krawl into a production pipeline.
Krawl is a deep-research API. The result is a cited markdown report. This page describes how we get there, where the failure modes live, and what we do when something goes wrong.
If a claim below contradicts what the engine actually does, treat the code as the source of truth and open a docs issue.
Methodology
What "deep research" means here
A deep run executes a recursive breadth × depth tree search:
- Plan (Sonnet 4.6). A structured research plan with topics and tasks.
- STORM perspectives (Haiku 4.5). 3–5 perspectives with key questions so the search tree explores multiple angles. Skipped for very short queries.
- Recursive tree (Haiku 4.5 for queries; Sonnet 4.6 for extraction
and gap analysis). Generate N queries per depth level, execute in
parallel across the enabled tools, extract structured learnings,
deduplicate (Jaccard ≥ 0.7), detect gaps, recurse with
depth - 1, breadth / 2. - Verified synthesis (Opus 4.7, exactly one synthesis call). Built on a retrieve-then-cite block — source metadata distinguishes original text, excerpts, provider summaries and links without inspected content. A collected URL alone does not verify a claim.
- Gap check + review/revise (Sonnet 4.6 / Opus 4.7). The draft is scored 0–1 by an independent review pass; if < 0.8, one or two revision passes run. Hard cap: two revisions.
Full pipeline detail: Architecture.
What "cited" means
Every numeric [n] in the report is a citation pointer into the source
list. The synthesis prompt enforces two rules that the engine then verifies:
- Source-bounded: the model is given a
<sources>block and may cite only those sources. A[n]outside the block is rejected and the chunk is re-asked. - Verified against text: each
[n]is verified against the fetched source content. The verification stream emits acitation_verifiedevent (verified: true|false) per citation; unverified citations trigger a re-pass.
A real source counter shows up in the result event under
sources_used; if you see fewer sources used than were fetched, that's
normal — only sources the model actually cited are surfaced.
What we don't claim
- We do not claim every fact in the report is true. We claim each cited fact came from a source we retrieved on the call and was verified against that source's text. The source itself can still be wrong.
- We do not pin a freshness guarantee on a deep run. The engine uses live search providers (Exa, Firecrawl, X, GitHub, CoinGecko, DeFi Llama, Semantic Scholar, PubMed, Reddit, HN, Wikipedia, Tavily, Serper, Brave, DuckDuckGo), but provider freshness varies. Where it matters, cross-check against the source link.
- We do not guarantee determinism. Same query twice can land on
different sources, and Opus's synthesis is sampled. If you need
reproducibility, set
seed(where supported) and pin the source list viaoutput_schema.
Failure modes (named)
Knowing what can go wrong is half of trust. Krawl emits these as structured failure types — agents can branch on them.
| Failure | Where it surfaces | What it means | What to do |
|---|---|---|---|
provider_4xx | per-tool, in audit | One search provider rate-limited or refused | Engine retries on a different provider; report often still ships |
provider_5xx | per-tool, in audit | Provider outage | Engine fails over (Bedrock → Anthropic → cross-provider) |
circuit_open | error event | Bedrock circuit breaker tripped (3 fails) | Anthropic direct fallback engages for 5 min |
cost_ceiling_hit | usage event (ceiling_hit: true) | Per-request cost ceiling reached mid-synthesis | Report finalises with whatever's gathered so far |
gap_unresolved | gap_detected w/o subsequent node_completed | A gap couldn't be filled before recursion exhausted | Report ships marked with gaps_unresolved > 0 |
citation_unverified | citation_verified: false | A [n] failed verification against source text | Engine re-asks the surrounding chunk; if persistent, citation is stripped |
review_below_threshold | review_pass score < 0.8 after pass 2 | Two revisions still didn't clear the bar | Report ships with the best draft + a quality_flag |
429_rate_limited | top-level 429 | Caller hit the per-IP / per-key rate limit | Honor Retry-After and back off (see Rate Limits) |
402_payment_required | top-level 402 | x402 challenge | Sign + retry with X-PAYMENT (see x402) |
The full audit trail of any specific run is at
GET /audit/{result_id}.
Refund policy
x402 payments are pay-per-use and non-refundable once settlement
succeeds. This is stated on the 402 challenge itself
(description: "… (pay-per-use, non-refundable)") so an agent can decide
before signing.
Two specific exceptions:
- Pre-settlement 503. If the server is at capacity, the 402 response
carries an empty
acceptsarray and is rejected before the facilitator's/settleruns. No funds move. - Post-settlement engine failure. If a paid request settles and then
the engine fails with a 5xx (not a 4xx your client caused), we'll
credit the request manually on review — open a ticket with the
transaction hash from
X-PAYMENT-RESPONSE. We don't promise SLA-grade automation here; it's a goodwill credit.
API-key requests follow the plan's terms — see Authentication for plan-scoped quotas and overage behavior.
Audit and verification surfaces
Two product surfaces let an agent or operator verify a specific run:
- Per-result audit log:
GET /audit/{result_id}returns every search, browse, extraction, and synthesis step for the run — what got called, with what argument, what came back. - Citation verification events: the SSE stream emits
citation_verifiedfor every[n]in the report, with the source URL and the supporting excerpt. See SSE Events →citation_verified.
For benchmark transparency — public scores on third-party benches and the methodology behind the Krawl Crypto Research Bench — see Benchmarks.
Security and data handling
- Auth:
X-API-Keyis HMAC-compared. Demo keys expire and are metered separately. - Headers: HSTS (2y, includeSubDomains),
X-Frame-Options: DENY,X-Content-Type-Options: nosniff. - Body limits: 1 MB normal, 50 MB on
/research/upload. - SSRF: webhook URLs are validated against an allowlist.
- Document upload: uploaded files are processed in-memory and discarded after the run completes; we do not train on user content.
- Logging: full request/response is sampled for ops and is purged on a 30-day rolling window. No prompts or reports are shared with third parties.
Reporting an incident
If you see a verified-true citation that misrepresents the source it
points to — or any other behavior that breaks the contract above —
open an issue at
github.com/ravidsrk/krawl/issues
or email team@krawl.sh. Include the result_id and the offending
[n]; we'll attach the audit trail.
Evidence time and access
Research sources carry optional retrieved_at (UTC), published_date,
updated_date, date provenance, access_status, source_record_id and
temporal_status. Missing fields on older reports mean unknown; never assign
export time as retrieval time. Access states are inspected_text,
partial_excerpt, provider_summary, metadata_only, fetch_failed, or
unknown. These describe available evidence, not claim support or truth.
A recent fetch does not make an old article current. Summary/metadata-only
results do not establish that the original text was read.
Optional source_policy.as_of sets a UTC evidence cutoff; dates after it are
quarantined in quarantined_sources, outside synthesis. Without it the cutoff
is research start. This is not a historical web archive; undated content
remains uncertain. See evidence methodology.
Publication/update dates are provider assertions. Exa, Tavily, Serper, Brave,
DuckDuckGo and TinyFish search results are labelled excerpts. Exa/Firecrawl
extractions and capped HTTP pages remain excerpts. The X search overview is
a provider summary; empty linked posts are metadata-only. Native X post bodies
that fit in the content limit are inspected text. Academic abstracts are excerpts;
Semantic Scholar year-only dates keep year precision. arXiv Atom published
and updated are kept separately. GitHub repository updated_at is an update,
not a publication date. Multi-provider crypto summaries do not establish that
the linked page was inspected. Missing provenance stays unknown.
HTML, PDF, DOCX, slides, Markdown and JSON exports include source observation limits. Retained results store those fields under the same ownership, deletion and retention rules as the report. ZDR runs do not persist them.
CI uses a synthetic, frozen cutoff cohort (2026-10-01 UTC) with labelled old/new conflicts, false premises, missing dates and partial X access. It tests propagation and filtering, not model correctness. No live FreshQA score or improvement is claimed; a current live cohort needs separately approved budget and labels.
Evidence coverage
The optional evidence_coverage result field gives descriptive counts of unique
exact URLs discovered, explicitly fetched, retained, referenced in outgoing
model input, and cited. Stages overlap: a retained search snippet may never
have had its original page fetched. It also reports explicit failed/unavailable
fetches, unknown fetch/access states, retained-host concentration, missing
publication dates and their known range. A model-input reference may contain
only metadata or a short excerpt; a citation is not a support verdict.
These counts do not establish representative sampling or correct selection
bias. Hostnames do not prove independent origins; mirrors may share a publisher.
Old reports without this field have unknown coverage. No extra LLM call is made;
the measured instrumentation overhead is reported as measurement_overhead_ms,
not a guarantee of zero added latency. See evidence methodology.
Corroboration observations
Learning records may include corroboration text-reuse observations. Exact and
near copies form candidate origin groups; these are not proven publishers or
independent sources. Overlapping words can contradict one another. Both
claim_support and independent_origins remain unassessed, and this heuristic
does not increase confidence or reject a unique primary record. Comparison is
bounded to 256 sources and 12,000 characters/1,000 tokens per source; a truncation
flag exposes incomplete comparison. These observations are not a poison detector.
These checks detect possible text reuse only. Factual poisoning and instruction attacks require separate evaluation. The live paired cohort remains pending.
Benchmarks
Krawl's published scores on FRAMES, SimpleQA, and FinSearchComp, plus the Krawl Crypto Research Bench — methodology, leaderboard, and scoring code.
Batch & Bulk Operations
Submit many research jobs in one call with POST /research/batch, or fan out parallel async tasks; plus the multi-result compare primitive