You give SCOUT a company. Ninety seconds later you have a BD brief that names their modality, their clinical stage, their manufacturing posture, who runs CMC, what they announced recently, and three specific questions to open a conversation with — sourced, cited, and costing about ten cents.
It works. It has produced 11 briefs and the most recent one was two weeks ago. That combination — a capable agent nobody is using — is the honest headline of this page.
scout_briefs and the deployed Edge Function source. Zero failed runs in its history.
| Job | On-demand single-company BD research brief for Account Atlas. |
| Harness · archetype | edge-functions · research-agent. Correct choice: a human clicks and waits, and the whole run fits inside a request. |
| Trigger | on_demand — the "Research this account" button in Account Atlas, or a direct POST. Also reachable via CHIEF as route=scout, mode=research. |
| Host | Edge Function scout-research on Transfer (jrfcfayphcmaxsixxupu), 526 lines. Not on bc-made. |
| Model | claude-sonnet-5, max_tokens: 4000, one synthesis call per run. |
| Observed cost | $0.05 – $0.12 per brief. Mean across 11 runs: $0.099. |
| Guardrails | Shared daily scrape budget (300/day, reserved via RPC) · 30-day scrape cache · 6 pages max per company · hard 422 when a company can't be resolved. |
| RED line | Read plus brief-write only. No Salesforce, pipeline, price or revenue writes. |
| Owner | Joe Sinclair. Last registry verification 2026-07-09. |
Four phases. The design principle throughout is gather deterministically, synthesise once — every source is fetched by plain code, and the model is called exactly one time, over only what was actually retrieved. That is why the briefs are specific rather than plausible.
company_id and a domain on Transfer. Reuses the existing identity graph rather than a name string.status: failed. It does not guess a domain and it does not proceed on a name alone.site:domain, across six fixed topics: pipeline, technology platform, about, manufacturing, news, leadership.freshness=py, 6 results — funding, clinical, partnership, appointments.sec.gov, IR pages, 10-K / 8-K / S-1. Turns a public company into a much richer brief.firecrawl_reserve_scrape(p_max_per_day: 300). If the reservation fails, the scrape does not happen — and the budget is shared with account-scrape, so the two agents cannot collectively overrun it.Why shared, not per-agentTwo agents with 300/day each is 600/day. A shared pool means the ceiling is the ceiling regardless of how many callers appear later — which is the only version that survives a third agent being added.
Behaviour at the capReturns status: 'failed' with 'no sources gathered (budget or fetch failure)' — HTTP 200, explicitly labelled. It degrades loudly.
What's actually happeningThe "SEC / press" step is not an EDGAR API call. It is a Brave search scoped to site:sec.gov plus press-release phrasing, returning 4 snippets. Same for news and contact background. Only ClinicalTrials.gov is a real structured API.
Why that's a defensible choiceSnippets are enough for a conversation-opening brief and cost almost nothing. Parsing actual filings is a different, much larger agent.
Consequence in the outputFinancial fields come back honest but thin — one real brief reads "reported Q1 2026 financial results (details not in source); no specific runway figures stated." The model correctly declines to invent. That is the system working.
claude-sonnet-5 call at max_tokens: 4000 over everything gathered, returning a fixed JSON shape.
status: 'partial', never a silent empty brief.And a talking point from the same brief"You've stated you're maintaining existing CDMO partners for the myositis registrational trial while transitioning to Cellares for commercial scale — how are you managing comparability/analytical bridging between the two manufacturing sources ahead of your 2027 BLA?"
Why it landsBecause the model only saw six pages of Cabaletta's own site plus their own press releases. Nothing generic could enter, because nothing generic was retrieved.
The gapGuardrail G-2 says generation gets a hold-out validator on a different model. SSO AGENT has one and it can reject. SCOUT does not. Its output goes straight to a human.
Why that is arguably correct hereA validator exists to stop bad output reaching the outside world. An SSO message gets sent to a prospect — it needs a gate. A SCOUT brief is read by a rep who is entirely capable of noticing it is wrong, and who is the validator.
huntsman or DOSSIER ever consumes SCOUT output programmatically, the human validator disappears and G-2 has to be honoured.Current mitigationSelf-declared confidence on every brief, plus a full source list — so a reader can check.
scout_briefs: markdown, JSON, sources, model, cost, resolved name and domain.scout-render for a branded PDF. Deliberately not awaited — the user gets the brief immediately.scrape_source: scout:*, so the next agent inherits it.render_status: done. The single pending is the very first row — a UX smoke test from 2026-07-08 that predates the render function being wired. So: not a bug, and the pattern holds.
Small enough to print in full — which is itself the finding.
| Date | Company | Status | Render | Cost | By |
|---|---|---|---|---|---|
| 2026-07-21 | Triumvira Immunologics | ok | done | $0.0977 | app |
| 2026-07-21 | Tr1X | ok | done | $0.0921 | app |
| 2026-07-13 | Mirror Biologics | ok | done | $0.0507 | app |
| 2026-07-13 | Obsidian Therapeutics | ok | done | $0.1115 | app |
| 2026-07-13 | Obsidian Therapeutics | ok | done | $0.1086 | app |
| 2026-07-10 | Outpace Bio | ok | done | $0.1228 | app |
| 2026-07-09 | Alloplex Biotherapeutics | ok | done | $0.1151 | app |
| 2026-07-09 | Verismo Therapeutics | ok | done | $0.0843 | app |
| 2026-07-09 | Obsidian Therapeutics | ok | done | $0.1043 | app |
| 2026-07-08 | Cabaletta Bio | ok | done | $0.1050 | scout |
| 2026-07-08 | Cabaletta Bio | ok | pending | $0.0956 | scout |
Read it plainlyThis is not a broken agent. It is a working agent that nobody reaches for. The briefs are good — genuinely good, as the Cabaletta example shows — and produced at a cost that makes the question "should we run SCOUT on this account" absurd to even ask. Ten cents.
Why that's likely happeningThe most plausible explanation is discoverability rather than distrust: the button lives on the Account Atlas page, so you have to already be there to know it exists. Nothing prompts a rep before a call to say "there is a brief available for this account, for ten cents."
Not a build taskSCOUT needs no engineering. It needs a habit.
What happenedObsidian Therapeutics has three briefs: 2026-07-09, and twice on 2026-07-13 (six minutes apart). Cabaletta has two, 49 minutes apart. Five of eleven briefs are repeats.
Why the cache didn't helpThe 30-day cache is on the scrape, not the brief. So a repeat run correctly avoids re-scraping, then pays for a fresh $0.10 synthesis anyway. The expensive half is the unguarded half.
FixCheck for a brief newer than N days before synthesising; offer the existing one with a "refresh anyway" option.
What's thereThe output schema has a full contact block — name, role, seniority, decision relevance, personalisation hooks. There is a dedicated Brave step (contactSnippets) to populate it.
What actually comes backIn the verified Cabaletta brief: contact_snippets: 0 and every contact field empty. The company half is rich; the person half is blank.
WhySCOUT is invoked from an account page with a company, not a person. With no name passed, contactSnippets returns immediately by design. The capability is built and simply not being fed.
FixPass a contact from the meeting or the contact record. Nothing to build.
The issueA brief is a snapshot. Cabaletta's cites a Cellares agreement from April 2026 and EULAR data from June. Read in December, several of those "recent news" lines are stale — and nothing in the UI says so.
Why future and not urgentEvery brief carries created_at, and the history list is visible on the account page. The information needed is present; it just isn't emphasised.
WhenWhenever adoption rises enough that old briefs get read at all.
SCOUT does everything the method page asks for. It refuses rather than guesses when it cannot resolve a company. It gathers deterministically and synthesises once. It has a shared budget ceiling rather than a private one. It degrades loudly, labelling partial results as partial. It reuses the identity graph instead of building a parallel one. Eleven runs, zero failures, ten cents each.
None of its three real limitations is an engineering problem. Two of them — the empty contact block and the missing dedup — are resolved by calling it differently. The third is that almost nobody calls it at all.
Which makes this page's recommendation a distribution recommendation, not a build one: put a brief in front of a rep before a meeting they already have booked, and see whether it gets read. That test costs about a dollar.