metalworks.contract, the part of the API you can depend on. There
aren’t many, and they all connect through one report.
The conversations behind a report
Every source — Reddit, Hacker News, the web, your own — produces items in the same two shapes, so the rest of metalworks doesn’t care where a quote came from:CorpusRecord— one thing people are talking about (a Reddit post, an HN story, a web page):id,source,url,title,text,author_hash,engagement,created_at, plus anextramap for anything source-specific (subreddit, domain, rating…).CorpusComment— a comment under a record (a reply), the same fields plus aparent_id.
The demand report and what’s inside it
mw.research(...) returns a Research bundle; the report itself is on .demand. Everything
else you generate later reads from this one report.
DemandReport— the output of demand research: a one-linedemand_summary(demand strength — the go/no-go isassess’s job), theranked_clusters(the real needs people voiced), webweb_findings, and market sizing. (audience_profileis currently alwaysNone— demographic inference was cut.) If a best-effort stage degraded,partialis set with a plain-languagecaveat.version,lineage_id, andparent_report_idtrack a report’s earlier versions when you update it.InsightCluster— one ranked need. Carries aclaim(the need, in plain words),distinct_author_count(how many different people raised it),breadth_count/breadth_unit(the same idea across sources — different people, or different sites for web pages),mention_count, asignalchip, ademand_scorethat ranks by how many people care over how viral one post was, and thequotesbehind it.ResolvedCitation— a verbatim quote. Itstextis the exact text of a real comment, and it carriessource_url(open it and read it yourself),source/source_name(e.g.reddit/r/Supplements), andengagement. The quote text and link are stored right on it, so a report makes sense on its own — even handed to someone without your saved data. A cluster with zero verified quotes never ships: metalworks drops anything it can’t back with a real quote.WebFinding— a fact pulled from the web. Itssource_urlcomes from the search tool’s citation data, never from model prose. No source, no finding.SegmentChoice/CandidateWedge— the forks the report surfaces instead of silently collapsing: distinct audiences you could target (each with anoverlapguard so near-identical ones aren’t offered as a real choice) and the narrowest things someone would pay for (each tied to the clusters behind it). The validation loop’s PIVOT aims at one of these. Deterministic callers readreport.default_segment/default_wedge; interactive ones setchosen_*.ReportDiff— what changed between two versions of a report: count deltas (threads, distinct voices, clusters, source distribution) plus themes added / faded / shifted. You get one back frommw.refresh(...)ormetalworks research diff. See the corpus.
ResearchBrief — the question, the subreddits to cover, success criteria,
and a relevance rubric. You rarely build one by hand: pass a question string straight to
.research(), or let Metalworks().plan(prompt) assemble one for you.
Everything points back to the report
Positioning, the design system, the build spec, and launch copy are all derived objects. Each one is generated from the report and links its claims back to the same quotes:PositioningBrief— your angle: who it’s for and why it’s different, built from the unmet needs in the report.CompetitorMap— the rivals to beat, eachgaptied to a real complaint someone posted.BuildSpec— a feature list where every feature maps to a real need (anything that can’t be tied to a quote is dropped), plus the surface to build on (web, mobile, CLI… — chosen with a one-line rationale, or pinned) and theScreens you need, each mapped to real features.ChannelStrategy/Channel— the test→focus channel experiments, eachrouting_signaltied to a real corpus entity; plus the per-channel assets and plan derived from them —ChannelAsset/AssetPart(channel-shaped drafts),DataReportAsset/DataReportItem(a corpus-derived data report with real counts + permalinks),GeoPlan(withParticipationTarget/CitabilityProbe/AnswerBrief),DistributionPlan(withPush/Stream),ChannelMetric/ChannelResult, and the build-feedLoopRequirement/ConversionSurfaceRequirement. Every claim-bearing line is backed by a quote; metalworks never posts.Landscape/ExistingSolution— the full “what exists today”: theCompetitorMapplus real shipped products (Product Hunt / web) matched to demand clusters with their traction.Assessment/ForkVerdict— the GO / PIVOT / NO-GO verdict, a deterministic gap over relative demand × landscape (the model only writes the rationale); a PIVOT carries the under-served fork to aim at.fork_verdictsis the un-collapsed per-fork answer (each fork’s GO/NO-GO + demand band +confidence);gapcarries the prevalence/percentile the strength self-calibrated from.ValidationResultis the validation loop’s outcome + decision log.
Reddit objects
The Reddit tools search, read, and (carefully) draft replies.RedditPost/RedditComment— what a thread looks like: title, body, score, permalink, and a saltedauthor_hash(never a raw username).SubredditIntel— community metadata: description, subscribers, rules, top posts.Opportunity— a thread metalworks found, plus a drafted reply and its compliance result. Nothing is ever posted from one without your explicit, per-action approval.ComplianceVerdict— the result of the offline gate over a draft:pass_,violations,confidence.DiscoveryContext— where you inject your own knowledge:voice_guidelines,winning_examples,pinned_notes,avoid, andpersonas.Persona/PersonaSet— voice profiles keyed by account type. Thebackgroundfield must be authentic; fabricated backstories are not allowed.
How they connect
Both sets of objects run on the same swappable protocols —ChatModel, EmbeddingProvider,
SearchProvider, CorpusReader, and the typed storage repos. See Extending
metalworks for the protocols, and the Protocols
reference for their exact shapes.