When Antigravity Skips Parts of a Long Attached PDF — and a Gate That Forces It to Cite Sources
How to handle the case where Antigravity answers confidently from a long attached PDF but quietly skips a clause. With working code: a prompt that forces citations, and a gate that verifies each cited quote actually exists in the PDF.
While preparing a store submission for one of the wallpaper apps I run as an indie developer, I attached the store guideline PDF (40-plus pages) to Antigravity and asked it to list anything around in-app purchases that might trip me up. The answer looked solid and was genuinely useful. But one clause about subscription price-change disclosure, sitting in the middle of the document, was simply missing. The agent answered as if it had read everything, so it took me a while to notice the gap.
This behavior — confidently answering from a long PDF while quietly skipping a part — is less a flaw in the attachment feature and more a question of how you hand over long context. Below, I'll lay out why the content thins out, then build something concrete: forcing the agent to show its evidence, and verifying that the evidence actually exists in the PDF.
Why a long PDF thins out inside the context
When you attach a whole PDF, its full text is poured into the model's context. Being in the context means it can be read, but "can be read" and "is referenced when answering" are different things. In long documents, attention spreads across the whole, the opening and closing are picked up more easily, and the small mid-document clauses are the ones most likely to slip through. In my own experience, the part that goes missing is always a short, unremarkable sentence somewhere in the middle.
A second trap is the quality of the PDF's text layer. Store PDFs are full of columns and tables, and the extracted text often comes out with its reading order scrambled. A table that looks natural to a human can end up with each item and its condition scattered across unrelated lines, so the agent fails to connect a clause with its exception.
So there are two things to address. First, narrow the range you hand over. Second, force the agent to state where its evidence came from, and verify it. Let's take them in order.
First, make it state where the evidence came from
The first thing that helps is constraining the shape of the answer. Free-form responses come back as summaries with no evidence. Instead, before the conclusion, require a structured page number and an original quote.
You answer strictly from the attached PDF. Do not fill gaps with general knowledge.
For each finding, output in this exact order:
1. page: the page number used as evidence (sequential page in the PDF)
2. quote: a verbatim quote from that page (20-60 characters, unchanged)
3. finding: the concrete impact on my app implied by the quote
For any item with no basis in the PDF, write "no matching passage" and do not guess.
At the end, output the list of page numbers you checked.
The key is the explicit "strictly from the attached PDF" and "do not fill gaps with general knowledge." A model can talk about store rules in general even without an attachment, so unless you forbid it, it will answer from common sense without reading the PDF. Limiting quotes to 20-60 characters matters because quotes that are too long drift during verification, and quotes that are too short cannot be uniquely located.
Even at this point, gaps become easier to spot. If the "list of page numbers checked" skews toward the front, that is a sign the middle is being skimmed. Still, whether each quote is correct is something a human would otherwise have to cross-check one by one. That is what we mechanize next.
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦You'll understand why a long attached PDF gets skimmed, and you can structurally reduce that context dilution
✦You'll be able to make the agent emit page and quote before its conclusion, and mechanically verify that each quote actually exists in the PDF
✦For high-stakes reviews like store submissions or spec checks, you'll have a concrete basis for trusting the agent's answer
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
Before verification, one move that reduces dilution at the source is splitting the PDF into sections and attaching only the relevant range. Handing over just the 8 pages about payments, rather than all 40, visibly cut down the misses.
Here is an example of splitting by page range with pypdf. If the PDF has bookmarks you can use them as boundaries, but many PDFs do not, so this keeps it simple by specifying the page ranges you confirmed by hand.
from pypdf import PdfReader, PdfWriterreader = PdfReader("store-guideline.pdf")# Specify section boundaries as (start page, end page exclusive), 0-indexedsections = { "01-account": (0, 6), "02-payments": (6, 14), "03-privacy": (14, 22),}for name, (start, end) in sections.items(): writer = PdfWriter() for i in range(start, end): writer.add_page(reader.pages[i]) out = f"section-{name}.pdf" with open(out, "wb") as f: writer.write(f) print(f"{out}: {end - start} pages")
Once split, drag only the relevant section in through the Add Context menu. Because the range the agent must reference is physically narrowed, quote accuracy goes up. Narrowing the range is the same philosophy as grounding via substring search in a large repository: rather than "hand over everything and pray," you "hand over exactly the range that matters."
That said, splitting too finely severs cross-references between clauses (such as "the exception in Section 3 follows Section 7"). For documents heavy on cross-references, it is safer to group related sections into a single piece.
A gate that checks whether each quote exists in the PDF
This is the heart of it. Even after you make the agent emit page and quote, there is no guarantee the quote is actually on that page. It can write a nonexistent page number or generate a plausible-looking sentence — a citation hallucination. So we set up a gate that matches each cited quote against the PDF's extracted text and rejects anything that does not exist.
As a setup, save the agent's answer as agent_citations.json (an array of page and quote). Since the earlier prompt forces structured output, extracting it is easy.
import jsonimport reimport unicodedatafrom pypdf import PdfReaderdef normalize(text): # Absorb width, whitespace, and newline variations to improve matching text = unicodedata.normalize("NFKC", text) return re.sub(r"\s+", "", text)reader = PdfReader("store-guideline.pdf")pages = [normalize(page.extract_text() or "") for page in reader.pages]with open("agent_citations.json", encoding="utf-8") as f: citations = json.load(f)failures = []for c in citations: page_idx = c["page"] - 1 quote = normalize(c["quote"]) if page_idx < 0 or page_idx >= len(pages): failures.append((c["page"], "page number does not exist")) elif quote and quote not in pages[page_idx]: failures.append((c["page"], "quote not found on that page"))if failures: for page, reason in failures: print(f"NG p.{page}: {reason}") raise SystemExit(1)print(f"OK: verified all {len(citations)} citations")
The point is that normalize flattens whitespace and width differences. Without it, the irregular line breaks in the extracted text would fail to match the quote, and even correct citations would be wrongly rejected. Conversely, flatten too aggressively and a sentence elsewhere may coincidentally match, which is why the prompt keeps quotes at 20 characters or more.
Once you decide to trust only the citations that pass this gate, you are no longer swayed by the agent's tone. A rejected citation is either a skip or a fabrication, so you re-attach just that page on its own and ask again.
Comparing the behavior, Before / After
Here is how it changes, using a price-disclosure check as the example.
Aspect
Before (whole PDF, free-form)
After (split + forced quotes + gate)
Answer shape
"Be careful with subscription wording," summary only
Concrete clause with page and quote
Misses
The mid-document price-change clause dropped
The checked-pages list makes the gap visible
Quote trust
No way to verify
Nonexistent quotes are rejected mechanically
Speed to fix
Blocked until a human notices the gap
Re-attach only the dropped page and fill it in
After looks like more work, but in practice it was the opposite. In the Before flow, a human had to shuttle back and forth with the PDF to confirm whether everything had really been read, and that was where most of the time went. Once the gate guarantees that each quote is real, the human can focus only on the dropped items.
Common pitfalls
Scanned PDFs have no text layer. A PDF that is just a scan of paper yields empty extracted text. Check whether text can be pulled before attaching.
# Check whether a text layer exists (i.e. it is not a scanned PDF)pdftotext -layout store-guideline.pdf - | head -c 200
If nothing comes out, you need to run OCR before attaching. A PDF with no extractable text is an image to the agent, and quote verification cannot hold.
Displayed page numbers drift from sequential ones. In a PDF where the body starts at page "3" because of a cover and table of contents, an agent answering with the displayed number conflicts with the sequential index in the verification script. State "sequential PDF page, starting at 1" in the prompt to prevent the drift.
Citation hallucinations happen quietly. The agent may generate a plausible sentence and attach a plausible-looking page number. If you confirm by eye alone without the gate, a human also feels "that sounds right" and lets it slide. That is exactly why it is safer to fall back on existence-matching rather than visual review.
Over-splitting severs cross-references. As noted, exception clauses that span sections are lost at the split boundary. For documents heavy on cross-references, keeping the split granularity coarse reduces misses.
When you update several apps alone, documents like store guidelines — where a single overlooked spot leads straight to a rejected submission — are exactly the ones where you cannot take the agent's confident summary at face value. Build the mechanism that backs quotes with existence once, and however long the document is, at least the correctness of the references is guaranteed by a machine.
The more you widen what you delegate to the agent, the more the value rises of having a way to confirm that it truly looked at the evidence. Pick one long PDF you have on hand, run it through the quote-forcing prompt and the verification script, and the skips become visible at a glance.
Share
Thank You for Reading
Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.