Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
8e3084c
fix(CI): move all platform jobs off self-hosted macOS runner to ubunt…
Apr 21, 2026
9b226b8
fix: introduce broadcasterLogger interface to fix strict-compiler typ…
Apr 21, 2026
b1064ea
refactor: split 4 oversized handler files into focused sub-files
airenostars Apr 21, 2026
38cc501
Merge pull request #1363 from Molecule-AI/refactor/split-large-handlers
molecule-ai[bot] Apr 21, 2026
19c0935
fix: add BroadcastOnly to broadcasterLogger and pass nil to LogActivity
Apr 21, 2026
75c5cd5
ci: trigger build
Apr 21, 2026
52e6bae
feat(runtime+scheduler): increment/decrement active_tasks counter (re…
molecule-ai[bot] Apr 21, 2026
1f41973
docs: workspace files API reference, skill catalog, and links
molecule-ai[bot] Apr 21, 2026
982d422
Merge pull request #1429 from fix/canvas-tooltip-clear-timer
molecule-ai[bot] Apr 21, 2026
c14e9e0
fix(canvas/test): add missing children:[] to setPendingDelete expecta…
molecule-ai[bot] Apr 21, 2026
870949b
fix(canvas/test): add children:[] to setPendingDelete + \' entit…
molecule-ai[bot] Apr 21, 2026
453f15a
Merge staging into infra/sre-work-2026-04-21
Apr 21, 2026
5b4f1fe
fix: remove duplicate SSRF functions from mcp_tools.go
Apr 21, 2026
0f786cf
fix: add validateRelPath and update LogActivity signature
Apr 21, 2026
81e7fbe
fix(handlers): change PluginsHandler.sources to SourceResolver interface
Apr 21, 2026
15c2931
chore: trigger CI for 81e7fbe SourceResolver interface fix
Apr 21, 2026
273dec8
fix(handlers): dedupe SSRF functions — ssrf.go is now canonical home
Apr 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 20 additions & 21 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ on:
branches: [main, staging]

# Cancel in-progress CI runs when a new commit arrives on the same ref.
# This prevents multiple stale runs from queuing behind each other and
# monopolising the self-hosted macOS arm64 runner.
# This prevents multiple stale runs from queuing and keeps the self-hosted
# macOS arm64 runner (publish-canvas-image, publish-workspace-server-image)
# available for the jobs that genuinely require it.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
Expand Down Expand Up @@ -57,7 +58,7 @@ jobs:
name: Platform (Go)
needs: changes
if: needs.changes.outputs.platform == 'true'
runs-on: [self-hosted, macos, arm64]
runs-on: ubuntu-latest
defaults:
run:
working-directory: workspace-server
Expand All @@ -70,6 +71,10 @@ jobs:
- run: go build ./cmd/server
# CLI (molecli) moved to standalone repo: github.com/Molecule-AI/molecule-cli
- run: go vet ./...
# golangci-lint-action uses a Linux Docker image (ubuntu is the only arch+OS
# combo the official image publishes for). Previously this step was pinned to
# [self-hosted, macos, arm64] because the Docker image can't run on macOS ARM.
# Now that the job itself runs on ubuntu-latest, the Docker image works natively.
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v9
with:
Expand All @@ -93,7 +98,7 @@ jobs:
name: Canvas (Next.js)
needs: changes
if: needs.changes.outputs.canvas == 'true'
runs-on: [self-hosted, macos, arm64]
runs-on: ubuntu-latest
defaults:
run:
working-directory: canvas
Expand All @@ -119,12 +124,11 @@ jobs:
name: Shellcheck (E2E scripts)
needs: changes
if: needs.changes.outputs.scripts == 'true'
runs-on: [self-hosted, macos, arm64]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run shellcheck on tests/e2e/*.sh
# `ludeeus/action-shellcheck` is a Docker action (Linux-only). We rely
# on shellcheck being pre-installed on the self-hosted runner instead.
# shellcheck is pre-installed on ubuntu-latest GitHub-hosted runners.
run: |
if ! command -v shellcheck >/dev/null 2>&1; then
echo "::error::shellcheck is not installed on the runner"
Expand All @@ -135,7 +139,7 @@ jobs:

canvas-deploy-reminder:
name: Canvas Deploy Reminder
runs-on: [self-hosted, macos, arm64]
runs-on: ubuntu-latest
needs: [changes, canvas-build]
# Only fires on direct pushes to main (i.e. after staging→main promotion).
if: needs.changes.outputs.canvas == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main'
Expand Down Expand Up @@ -181,24 +185,19 @@ jobs:
name: Python Lint & Test
needs: changes
if: needs.changes.outputs.python == 'true'
runs-on: [self-hosted, macos, arm64]
runs-on: ubuntu-latest
defaults:
run:
working-directory: workspace
steps:
- uses: actions/checkout@v4
# setup-python@v5 cannot write to /Users/runner (GitHub-hosted path) on
# the self-hosted macOS arm64 runner (user: <runner-user>) and also hits
# EACCES on /usr/local/bin due to macOS SIP. Skip it — Homebrew installs
# Python 3.11 at /opt/homebrew/opt/python@3.11 which is already on PATH.
- name: Verify Python 3.11 (Homebrew)
run: |
export PATH="/opt/homebrew/opt/python@3.11/bin:/opt/homebrew/bin:$PATH"
python3.11 --version
echo "/opt/homebrew/opt/python@3.11/bin" >> "$GITHUB_PATH"
echo "/opt/homebrew/bin" >> "$GITHUB_PATH"
- run: pip3.11 install -r requirements.txt pytest pytest-asyncio pytest-cov
- run: python3.11 -m pytest --tb=short -q --cov=. --cov-report=term-missing
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: pip
cache-dependency-path: workspace/requirements.txt
- run: pip install -r requirements.txt pytest pytest-asyncio pytest-cov
- run: WORKSPACE_ID=ci-placeholder python -m pytest --tb=short -q --cov=. --cov-report=term-missing

# SDK + plugin validation moved to standalone repo:
# github.com/Molecule-AI/molecule-sdk-python
4 changes: 2 additions & 2 deletions canvas/src/app/orgs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ function CheckoutBanner() {
<div className="mb-6 rounded-lg border border-emerald-700 bg-emerald-950 p-4">
<p className="text-sm text-emerald-200">
✓ Payment confirmed. Your workspace is spinning up now — this page
refreshes automatically when it&apos;s ready.
refreshes automatically when it's ready.
</p>
</div>
);
Expand Down Expand Up @@ -318,7 +318,7 @@ function EmptyState({ banner }: { banner?: React.ReactNode }) {
<Shell>
{banner}
<p className="text-zinc-300">
You don&apos;t have any organizations yet. Create one to get started — your
You don't have any organizations yet. Create one to get started — your
workspace spins up automatically once billing is set up.
</p>
<div className="mt-6">
Expand Down
1 change: 1 addition & 0 deletions canvas/src/components/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export function Tooltip({ text, children }: Props) {
}, []);

const onBlur = useCallback(() => {
clearTimeout(timerRef.current);
setShow(false);
}, []);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ describe("ContextMenu — keyboard accessibility", () => {
id: "ws-1",
name: "Alpha Workspace",
hasChildren: false,
children: [],
});
expect(closeContextMenu).toHaveBeenCalled();
});
Expand Down
4 changes: 2 additions & 2 deletions docs/agent-runtime/workspace-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ External workspaces run outside the platform's Docker infrastructure — on your
| Liveness | Docker health sweep | Heartbeat TTL (90s offline threshold) |
| Registration | Automatic at container start | Manual: `POST /workspaces` + `POST /registry/register` |
| Token | Inherited from container env | Minted at registration, shown once |
| Secrets | Baked in image or env var | Pulled from platform at boot via `GET /workspaces/:id/secrets/values` |
| Secrets | Baked in image or env var | Pulled from platform at boot via `GET /workspaces/:id/secrets` |

### Registration flow

Expand Down Expand Up @@ -185,7 +185,7 @@ The platform returns a 256-bit bearer token — save it, it is shown only once.
**3. Pull secrets at boot:**

```bash
curl http://localhost:8080/workspaces/ws-xyz/secrets/values \
curl http://localhost:8080/workspaces/ws-xyz/secrets \
-H "Authorization: Bearer <your-token>"
```

Expand Down
2 changes: 1 addition & 1 deletion docs/blog/2026-04-21-skills-vs-bundled-tools/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Here's how the comparison lands:

If you want to evaluate Molecule AI's skills coverage, start here:

→ [MCP browser automation guide](/docs/blog/browser-automation-ai-agents-mcp) — browser tools via Chrome DevTools Protocol, same capability as Hermes' built-in browser
→ [MCP browser automation guide](/blog/browser-automation-ai-agents-mcp) — browser tools via Chrome DevTools Protocol, same capability as Hermes' built-in browser
→ [TTS and image generation skills](/docs/guides/skill-catalog) — community-contributed, versioned, swappable
→ [Org-scoped API keys](/docs/guides/org-api-keys.md) — production auth and audit

Expand Down
196 changes: 196 additions & 0 deletions docs/guides/skill-catalog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# Skill Catalog

Skills extend what a workspace agent can do — from browser automation
and TTS to research tools and custom API integrations. This page covers
available skill types, how to install them, and how to manage their
versions.

> **Note:** Molecule AI does not ship a hosted skill marketplace. All
> skills are installed from local packages, GitHub URLs, or community
> bundles. See [Skill Lifecycle](#lifecycle) for how to publish and
> distribute skills within your org.

## Available Skill Types

The skills ecosystem covers the same capabilities as Hermes Tool Gateway
and more:

| Category | Skill | What it does | Provider options |
|----------|-------|-------------|-----------------|
| **Browser** | `browser-automation` | Chrome DevTools Protocol via MCP — navigate, query DOM, screenshot, fill forms. Same engine as Hermes' built-in browser tool. | Built-in (CDP); swap via skill version |
| **TTS** | `tts` | Text-to-speech generation. Streams audio to output. | OpenAI, ElevenLabs, or self-hosted |
| **Image gen** | `image-generation` | Generates images from text prompts. | OpenAI DALL·E, Stability AI, or self-hosted |
| **Web search** | `web-search` | Structured web search with result parsing. | Brave, SerpAPI, or custom |
| **Research** | `arxiv-research` | Searches and summarizes arXiv papers. | Community bundle |
| **Code** | `code-analysis` | Static analysis, diff review, complexity scoring. | Built-in |
| **SEO** | `seo-audit` | Lighthouse audit + GSC keyword extraction. | Built-in |
| **Social** | `social-post` | Formats and posts to social channels. | Built-in |

All skills are open source. Source is visible — inspect the `SKILL.md`
and `tools/` before installing.

## Installing a Skill

### From the built-in catalog

```bash
# Install browser automation
molecule skills install browser-automation

# Install TTS with a specific provider
molecule skills install tts --provider openai

# Install a specific version
molecule skills install browser-automation --version 1.2.0
```

### From GitHub

```bash
molecule skills install \
https://github.com/acme/molecule-skills/tree/main/browser-automation
```

### From a community bundle

Community skills are hosted on GitHub and referenced by slug:

```bash
molecule skills install arxiv-research --from community
```

Community skills are reviewed by the Molecule AI team before being
listed. Submit a skill for review by opening a PR against
[`molecule-ai/skills`](https://github.com/Molecule-AI/skills).

## Installing via config.yaml

Skills can also be declared in the workspace config file:

```yaml
skills:
- name: browser-automation
source: builtin
- name: tts
source: builtin
config:
provider: openai
- name: arxiv-research
source: community
```

On workspace boot, the runtime validates each skill and loads the
`SKILL.md` + tools into the agent's context.

## Version Management

Skills are versioned with semantic versioning. Pin to a known-good
release to prevent unexpected behavior changes:

```bash
# Pin to a specific version
molecule skills install tts --version 1.1.0

# Upgrade to latest
molecule skills upgrade tts

# View installed version
molecule skills list
```

Upgrading is safe — the skill loader validates the new package on
installation. If the new version has breaking changes, the workspace logs
a warning and keeps the previous version active until you restart.

## Custom Skills

Write a skill for your team's specific workflow:

```bash
# Scaffold a new skill
molecule skills init my-custom-skill
```

This creates:

```
skills/my-custom-skill/
+-- SKILL.md # instructions + frontmatter
+-- tools/
| +-- my_tool.py # MCP tool using @tool decorator
+-- examples/ # few-shot examples
+-- templates/ # reference files
```

See [Skills Reference](../agent-runtime/skills.md) for the full
`SKILL.md` format and frontmatter schema.

## Skill Lifecycle

```
Author writes SKILL.md + tools/
|
v
Install into workspace (local or GitHub)
|
v
Workspace loads skill on next boot / hot-reload
|
v
Agent sees skill in tool context
|
v
(Optional) Publish to org bundle or community
```

**Publishing to your org:** Bundle skills with workspace templates so
every new workspace in a role gets the same capability set:

```bash
molecule skills bundle my-custom-skill --output ./org-templates/my-role/
```

**Publishing to the community:** Open a PR against
[`molecule-ai/skills`](https://github.com/Molecule-AI/skills) with a
complete skill package. Community skills are reviewed for security and
correctness before listing.

## Removing a Skill

```bash
molecule skills uninstall browser-automation
```

Or remove from `config.yaml` and trigger a hot-reload by touching the
file:

```bash
touch /configs/config.yaml
```

The workspace detects the change, rescans skills, and updates the Agent
Card within ~3 seconds.

## Troubleshooting

**Skill not found:** Check the skill name matches the catalog exactly.
Skill names are lowercase with hyphens (`browser-automation`, not
`browser_automation` or `BrowserAutomation`).

**Skill loads but tools are missing:** Verify the `tools/` folder
contains valid Python files with `@tool`-decorated functions. See
[Skills Reference — Tool Interface](../agent-runtime/skills.md#tool-interface).

**Provider auth error:** Ensure the required environment variable (e.g.
`OPENAI_API_KEY`) is set in the workspace config or secrets.

## Related Docs

- [Skills Reference](../agent-runtime/skills.md) — Full SKILL.md format,
frontmatter schema, and tool interface
- [Config Format](../agent-runtime/config-format.md) — How skills are
declared in `config.yaml`
- [Plugin System](../plugins/overview.md) — Installing full plugin
packages (skills + MCP servers + shared rules)
- [Remote Agent Tutorial](../tutorials/register-remote-agent.md) —
Installing skills on remote (external) agents
2 changes: 1 addition & 1 deletion docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ The response includes your bearer token — save it now. It is shown only once.
```bash
AGENT_TOKEN="the-token-from-step-2"

curl "$PLATFORM/workspaces/$WORKSPACE_ID/secrets/values" \
curl "$PLATFORM/workspaces/$WORKSPACE_ID/secrets" \
-H "Authorization: Bearer $AGENT_TOKEN"
```

Expand Down
Loading
Loading