Reading Unstructured Sources
Outcome: a two-step extraction that turns prose into a quoted fact and a filterable value, tested on the sources your own workflow depends on.
- Surface
- App and MCP server
- Level
- Intermediate
- Uses
- linkedin_job_listings · linkedin_page_posts · AI extraction
- Credits
- ~15 for a 20-row test
- Prerequisite
- Lesson 08
What counts as unstructured
Anything written for a human rather than for a filter:
| Source | What is hiding in it |
|---|---|
| Job posts | Tools in the stack, team size, the problem they are hiring to solve, budget signals |
| LinkedIn posts | Launches, milestones, hiring pushes, strategic direction |
| Case studies | Their real ICP, in their own words, with outcomes |
| Pricing pages | Buyer type, contract shape, whether procurement is involved |
| Filings and reports | Segment revenue, stated priorities, risks they name |
| Reviews | Complaints — the sharpest source of a wedge |
Job posts are the highest-yield of these by a distance. A single engineering job post routinely names five tools, the team size, and the project it is being hired for.
Extract, then classify
One call that both reads and judges gives you an answer you cannot audit. Two steps give you an answer with its evidence attached.
Step 1 — extract, verbatim
“From this job post, list every named software tool, exactly as written. Return a comma-separated list. If none, return: none.”
Verbatim matters. It keeps step 1 checkable against the source.
Step 2 — classify the extract
“Given this list of tools, does it include a data warehouse? Answer: Yes, No, Unknown.”
Step 2 reads only step 1’s output. It is cheap, deterministic-ish, and if the verdict is wrong you can see immediately which step failed.
The pattern generalizes: extract the raw fact, then decide about it. One column each.
Always quote the evidence
Every extraction column should return the fragment it drew from.
Return exactly two lines:
FINDING: <the extracted value, or none>
QUOTE: <the sentence from the source that supports it, verbatim, max 25 words>Three reasons this is worth the extra output:
- You can verify without re-fetching the source.
- The quote is usable in outreach — quoting their own job post is unusually strong personalization.
- A finding with no quote is a hallucination you can filter out automatically.
Make “no quote means no finding” a hard rule enforced by a formula column. It removes almost every invented answer at zero cost, because a model that made something up rarely produces a supporting quote that survives a length and presence check.
Long documents
Filings and long reports exceed what fits comfortably in one call, and quality degrades well before the hard limit.
- Target the section. Ask for the part you need — “the risk factors section” — rather than the whole document.
- Extract, then reason. Pull the relevant passages first, then run the judgement over the extract.
- Never summarize the whole thing. A summary of a 200-page document tells you what the document is about, which you already knew, and loses the specific fact you wanted.
When the source cannot answer
The abstain path again, and it is worth being explicit about the difference between two kinds of nothing:
| Case | Return |
|---|---|
| Source read, fact genuinely absent | none — a real finding |
| Source unreachable, empty or wrong | error — not a finding |
Collapsing these into one blank value means “they do not use a warehouse” and “we could not read the page” become indistinguishable, and any score built on it is wrong for the second group.
Do this now
Pick your source and fact
Job posts and tools in the stack is the best first pair.
Pull the raw source
linkedin_job_listings for job posts, linkedin_page_posts for social.
Write the extraction prompt
Verbatim, with FINDING and QUOTE lines.
Run on 20 rows and check quotes
Open five sources yourself and confirm the quote is really there.
Add the classification step
Reading only the extract.
Add the no-quote filter
Findings without a supporting quote are dropped.
Separate none from error
Two distinct values, and count both per run.
Check your work
- Extraction returns verbatim text plus a supporting quote
- Classification reads the extract, not the source
- Findings without quotes are filtered out
noneanderrorare distinguishable- You verified five quotes against the live source
Where this breaks
Asking one call to read and judge at once is where invented facts enter a dataset. The model produces a confident verdict with no traceable basis, and because the verdict is well-formatted it flows into the score, the gate and the copy without resistance. Splitting extraction from classification costs one extra cheap column and makes every wrong answer traceable to a step.
Further automation
Extraction over job posts feeds directly into Hiring Signals, where the same reading produces both a qualification and a timing trigger. Once the extraction column is trustworthy, the signal course is mostly about cadence rather than new technique.
Next lesson
10 — AI as an enrichment fallback, where the Enrich module begins.
Reference for this lesson: linkedin_job_listings, linkedin_page_posts, Company job listings, AI agents.