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.
| Protocol | Import | Default(s) | How-to |
|---|---|---|---|
ChatModel | metalworks.llm | Anthropic / OpenAI / Google / OpenAI-compatible | Custom ChatModel |
EmbeddingProvider | metalworks.embeddings | Google, OpenAI | Protocols |
SearchProvider | metalworks.search | Exa, Tavily | Protocols |
CorpusReader / CommentSource | metalworks.research.deps | Arctic Shift | Use your own corpus |
| storage repos | metalworks.stores | MemoryStores, SqliteStores | Bring your own store |
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 stages are public functions you can wire into your own flow. Research stages (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, ...)— grounded or external-search web findings.triangulate(deps, ...)— link Reddit clusters to web findings.run_research(deps, brief=...)— the whole thing, if you want it.
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?generate_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.