Metalworks facade is the
easy path; underneath it is a kit of small, independent pieces. This page is the
map: what each piece is, and how to swap or compose it.
Swappable protocols
Each protocol isruntime_checkable and has a default implementation behind a
pip extra. Implement the protocol and pass your object anywhere the default is
expected.
A source is the seam that turns “Reddit research” into “research over any source”. It comes
in three lanes — a grounding connector that yields quotable records, a magnitude
provider that attaches an absolute number to a theme, or an agentic discovery provider that
reaches the long tail. Each is its own small protocol, registered append-only; see
Build a source.
Anything you don’t pass to
Metalworks(...) is resolved from the environment.
Anything you do pass is used verbatim — that’s how you swap a layer.
Composable functions
You don’t have to use the facade or the end-to-end pipelines. The steps are public functions you can wire into your own flow. Research steps (metalworks.research):
pick_target_subreddits(deps, brief=...)— LLM-suggested communities.run_exploration_triage(deps, ...)— three-bucket relevance triage.hydrate_submissions(...)/hydrate_comments(...)— pull a corpus into a repo.synthesize(deps, ...)— cluster comments into ranked insights.web_research(deps, ...)— web findings, backed by real quotes or source URLs.triangulate(deps, ...)— link Reddit clusters to web findings.run_research(deps, brief=...)— the whole thing, if you want it.
metalworks.research) — each takes a
DemandReport and traces its output back to the report’s real quotes:
build_positioning_brief(deps, report)— your positioning angle + a price read, backed by real quotes (metalworks.research.synthesis).run_competitor_map(deps, report)— direct / adjacent / status-quo rivals, each with an exploitable gap backed by a real complaint.build_spec_from_report(deps, report, positioning=None, surface="auto")/scaffold(spec, report, dest)(metalworks.build) — aBuildSpec(each feature mapped to a real demand cluster; withsurface="auto"it also picks the surface + a rationale and sketches feature-grounded screens) + a project scaffold for your own coding agent. metalworks specs and scaffolds; it writes no product code. See the Build spec.build_channel_strategy(deps, report, positioning=None)/distribution_requirements(channels)— the test→focus channel experiments + the embedded-loop / conversion-surface build requirements.build_channel_assets(deps, report, channels, positioning=None)/build_data_asset(deps, report, kind="complaint_index")— drafting-only channel-shaped assets (never posts) + a corpus-derived data report with real counts and permalinks.build_geo_plan(deps, report)/plan_distribution(report, channels)/channel_metrics(channels)— the GEO / LLM-citability stream, the pushes-and-streams plan, and the per-channel success metrics. See Distribution.
Metalworks facade —
mw.positioning(research), mw.landscape(...) (the competitive map + existing solutions),
mw.design(...), mw.build_spec(...) / mw.scaffold(...),
mw.channel_strategy(...) / mw.channel_assets(...) / mw.data_asset(...) / mw.geo(...) /
mw.distribution_plan(...) — which thread
the one resolved ResearchDeps for you. See the walkthrough.
Reddit + discovery (metalworks.reddit, metalworks.discovery):
RedditSearch— search, comments, subreddit rules. No OAuth needed.fetch_subreddit_intel(...),fetch_inbox(...),RedditOAuth— intel, inbox, posting.filter_post(model, post, context)— is this thread worth engaging?draft_reply(chat, post, persona, account_type, context)— draft a reply in a voice.heuristic_check(text)/llm_judge(...)— the deterministic gate, then the escalation.run_discovery(deps, queries=...)— the whole filter → generate → gate loop.