llms.txt, then go.
The one entry point
mw.research(question, subreddits=[...]) -> Research— demand research (theDemandReportis on.demand).mw.reddit.search / subreddit / comments / rules / inbox / post— Reddit surfaces.mw.discovery.run / filter / generate— discovery loop + building blocks.
MissingKeyError (with a fix string) surfaces only when a
call needs a key. Every error carries error_code, message, fix, and docs_url — relay
the fix verbatim.
MCP tools (the language-agnostic surface)
Runmetalworks mcp serve (stdio). 26 tools are registered. The full table — every
tool, whether it needs a key, its purpose, and params — is the MCP tools
reference. The split by key requirement:
- Zero-key: the data + deterministic tools —
compliance_lint,reddit_search_posts,reddit_get_post_comments,reddit_subreddit_info,reddit_subreddit_rules,arctic_list_months,arctic_pull_threads,corpus_stats,research_list_runs,research_get_report,channel_plan_build,content_plan_from_report. No provider key needed ([reddit]/[arctic]extras where noted). - Key-gated: anything that calls a model —
research_plan_brief,research_start/research_status/research_result,generate_reply,discovery_run, and the synchronous report-derived tools (run after a stored report exists):positioning_from_report,competitor_map_from_report,surface_recommend,ux_skeleton_build,site_render,launch_assets_build,build_spec. - Posting (the security boundary):
reddit_post_commentrequires aconfirm_tokenemitted by acompliance_lintpass over that exact text andMETALWORKS_ALLOW_POSTING=1. There is no override.
The async job pattern
Research and discovery take minutes. Do not call a blocking tool and wait — useresearch_start → research_status → research_result. The synchronous Python
mw.research(...) is for scripts, not for tool-call timeouts.
Rules that matter
- Posting is gated and irreversible. A blocked draft is refused before it reaches
Reddit; every attempt is logged to
~/.metalworks/post-log.jsonl. Never try to route around the compliance gate. - Authentic engagement only. No fabricated personas or backstories. The
Persona.backgroundfield must be real. - Every claim is backed by a real quote. Quotes are exact-matched against stored comments; web URLs come from citation metadata. Don’t present model-authored text as a sourced quote.
- Pick models by ref.
Metalworks(model="provider/model"); point at any OpenAI-compatible endpoint withbase_url. See Configuration.
Where to look
- Python SDK — the facade surface.
- Extending metalworks — the swappable protocols + functions.
- Protocols — exact protocol shapes.
llms.txt— the machine-readable index.