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>
4.4 KiB
Molecule AI Codebase Conventions
These rules apply to every agent working on the Molecule AI / Molecule AI codebase. They are lessons learned from real bugs — not style preferences. Violating them causes production failures.
Canvas (Next.js 15 App Router)
'use client' — NON-NEGOTIABLE
Every .tsx file in canvas/src/ that uses React hooks (useState, useEffect,
useCallback, useMemo, useRef), Zustand stores (useCanvasStore, useSecretsStore),
or event handlers (onClick, onChange) MUST have 'use client'; as the very first
line. Without it, Next.js renders the component as server HTML and React never hydrates
it — buttons appear but silently don't respond to clicks.
This has caused two reverted PRs. Always run this check before reporting done:
cd canvas
for f in $(grep -rl "useState\|useEffect\|useCallback\|useMemo\|useRef\|useStore\|onClick\|onChange" src/ --include="*.tsx"); do
head -3 "$f" | grep -q "use client" || echo "MISSING 'use client': $f"
done
Zustand Selectors — No New Objects
Never call a function that returns a new object inside a Zustand selector:
// BAD — creates new object every render → infinite re-renders
const grouped = useSecretsStore((s) => s.getGrouped());
// GOOD — use useMemo with stable selector values
const secrets = useSecretsStore((s) => s.secrets);
const grouped = useMemo(() => groupSecrets(secrets), [secrets]);
Dark Zinc Theme — No Light Colors
The canvas is dark-themed. Every new component must use:
- Backgrounds:
zinc-900,zinc-950,#18181b,#09090b - Text:
zinc-300,zinc-400,#d4d4d8,#a1a1aa - Accents:
blue-500,blue-600,violet-500 - Borders:
zinc-700,zinc-800 - Never:
white,#ffffff,#f5f5f5, or any light gray
API Response Shapes
Always verify the actual platform API response format before writing fetch code.
Check the Go handler or test with curl — don't assume. Past bug: FE assumed
GET /settings/secrets returned a flat array but it returns { secrets: [...] }.
Platform (Go)
SQL Safety
- Always use parameterized queries (
$1,$2), never string concatenation - Use
ExecContext/QueryContextwith context, never bareExec/Query - Always check
rows.Err()after iterating result sets - JSONB: convert
[]bytetostring()and use::jsonbcast
Access Control
- Every endpoint touching workspace data must verify ownership
- A2A proxy calls go through
CanCommunicate()— new proxy paths must respect it - System callers (
webhook:*,system:*,test:*) bypass viaisSystemCaller()
Container Lifecycle
- Use
ContainerRemove(Force: true)to stop containers — neverContainerStop+ContainerRemoveseparately (restart policy race condition causes zombies) - Always reap zombie processes:
proc.wait()afterproc.kill()with a timeout
Workspace Runtime (Python)
Error Sanitization
Never emit raw exception messages or subprocess stderr to the user. Use
sanitize_agent_error() which exposes the exception class name but strips
the message body (which can leak tokens, paths, and stack traces).
System Prompt Hot-Reload
System prompts are re-read from /configs/system-prompt.md on every message.
Always use encoding="utf-8", errors="replace" when reading prompt files.
Inter-Agent Communication
Parallel Delegation
Use delegate_task_async to send tasks to multiple peers simultaneously.
Don't serialize what can be parallel — fire all async delegations, then poll
check_task_status to collect results as they finish.
Side Questions
Any agent can ask a peer a direct question via delegate_task (sync) without
going through the lead. FE can ask BE "what's the API response format?" mid-task.
Use this to avoid guessing — it's faster than getting it wrong.
Proactive Updates
Use send_message_to_user to push status updates to the CEO's chat at any time.
Don't wait until everything is done to report — acknowledge immediately, update
during long work, deliver results when complete.
Before Reporting Done
Every agent, regardless of role, must verify their own work before claiming completion:
- Read back every file you changed — confirm it looks right
- Run the relevant test suite (
npm test,go test,python -m pytest) - Run the relevant build (
npm run build,go build) - Check for framework-specific gotchas (the
'use client'grep above) - If you can imagine a way your change could break, test that scenario