Forked clean from public hackathon repo (Starfire-AgentTeam, BSL 1.1) with full rebrand to Molecule AI under github.com/Molecule-AI/molecule-monorepo. Brand: Starfire → Molecule AI. Slug: starfire / agent-molecule → molecule. Env vars: STARFIRE_* → MOLECULE_*. Go module: github.com/agent-molecule/platform → github.com/Molecule-AI/molecule-monorepo/platform. Python packages: starfire_plugin → molecule_plugin, starfire_agent → molecule_agent. DB: agentmolecule → molecule. History truncated; see public repo for prior commits and contributor attribution. Verified green: go test -race ./... (platform), pytest (workspace-template 1129 + sdk 132), vitest (canvas 352), build (mcp). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.6 KiB
Bundle System
A workspace bundle is the portable unit of the platform. It is a single .bundle.json file that captures everything needed to recreate a workspace anywhere.
Bundle Format
{
"schema": "1.0",
"id": "seo-agent-vancouver",
"name": "Vancouver SEO Agent",
"description": "Bilingual EN/ZH SEO page generator",
"tier": 1,
"model": "anthropic:claude-sonnet-4-6",
"system_prompt": "...full prompt...",
"skills": [
{
"id": "generate-seo-page",
"name": "Generate SEO Landing Page",
"description": "...",
"files": {
"SKILL.md": "---\nname: Generate SEO Landing Page\ndescription: ...\n---\n\nInstructions for the agent...",
"tools/write_page.py": "def write_page(keyword, lang):\n ...",
"tools/check_gsc.py": "def check_gsc(url):\n ..."
}
}
],
"tools": [
{ "id": "web_search", "config": {} },
{ "id": "gsc_api", "config": { "scopes": ["search-console"] } }
],
"prompts": {
"prompts/page-generation.md": "...full content...",
"templates/renovation-page.html": "...full content..."
},
"sub_workspaces": [],
"agent_card": { "...": "A2A card snapshot" },
"author": "hongming",
"version": "1.2.0"
}
Skill Serialization
Each skill folder is serialized into a files dict — every file in the skill folder becomes a key (relative path) with its content as the value. No special treatment for any file type — SKILL.md, tool scripts, templates, and any other files are all serialized the same way.
def serialize_skill(skill_path: Path) -> dict:
skill_data = {"id": skill_path.name, "files": {}}
for file in skill_path.rglob("*"):
if file.is_file():
rel = str(file.relative_to(skill_path))
skill_data["files"][rel] = file.read_text()
# name/description extracted from SKILL.md frontmatter
md = skill_data["files"].get("SKILL.md", "")
skill_data["name"] = extract_frontmatter(md, "name")
skill_data["description"] = extract_frontmatter(md, "description")
return skill_data
On import, the importer reverses the process — it writes each key back as a file under the skill folder:
def deserialize_skill(skill_data: dict, target_path: Path):
skill_dir = target_path / skill_data["id"]
for rel_path, content in skill_data["files"].items():
file_path = skill_dir / rel_path
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(content)
What Is Included
- The full system prompt text
- All skill files (every file in each skill folder, inlined as strings in a
filesdict) - All prompt templates (markdown files, inlined)
- All asset files (HTML templates, etc., inlined)
- Tool configurations (which tools to use, how configured)
- Sub-workspace bundles recursively (for team workspaces)
- A snapshot of the Agent Card
What Is NOT Included
- API keys or secrets — buyer brings their own
- Memory or conversation history — buyer starts fresh
- Database data — not portable
Recursive Sub-Workspaces
sub_workspaces is an array of nested bundles. A team workspace contains the full bundles of all its members. The importer walks the tree recursively and provisions each workspace it finds.
How Bundles Are Built
The workspace-configs-templates/ folder contains the source files for each workspace type. The bundle-compile.sh script walks each folder and inlines all files into a single workspace.bundle.json. This is the compiled artifact — like a built binary from source files.
Import/Export Workflow
Export
- Right-click node on canvas
- Select "Export as bundle"
- Platform serializes the running workspace via
GET /bundles/export/:id - Downloads
seo-agent.bundle.json
Import
- Drag
.bundle.jsononto canvas - Canvas sends
POST /bundles/import - Platform importer (
bundle/importer.go) walkssub_workspacesrecursively - Each workspace gets a container provisioned with extracted config
- New nodes appear on canvas
Partial Import Failure
If a bundle contains sub-workspaces and one fails to provision:
- Successfully provisioned workspaces remain running
- Failed workspaces get
WORKSPACE_PROVISION_FAILEDevents - The parent workspace still comes online (it can operate with fewer sub-workspaces)
- Canvas shows failed sub-workspace nodes in red with retry buttons
- User can retry individual failed sub-workspaces without re-importing the whole bundle
ID Generation on Import
The platform always generates fresh workspace IDs on import. The original bundle id is stored as source_bundle_id in the workspace record for traceability.
This means:
- You can import the same bundle twice to run two instances
- The bundle
idis the template identity, the workspaceidis the instance identity - You can trace which template a workspace came from
- You can find all instances of the same bundle
- You can push updates from the original template
Duplicate
Export + re-import with new IDs (always — no overwriting).
Future: Marketplace
Bundles are the unit of sale:
- A seller lists a bundle with a price
- A buyer purchases it
- The platform provisions it in the buyer's environment with their own API keys
- The seller's prompts and skills are included
- Like buying a Shopify theme — you get the design and logic, not the store's data
Related Docs
- Workspace Runtime — Source files that compile into bundles
- Platform API — Import/export endpoints
- Canvas UI — Drag-and-drop bundle interactions