Skill: wyuc/openmaic (version 0.3.1)

--- name: openmaic description: Guided SOP for setting up and using OpenMAIC from OpenClaw. Use when the user wants to clone the OpenMAIC repo, choose a startup mode, configure recommended API keys, start the service, or generate a classroom from requirements or a PDF. Run one phase at a time and ask for confirmation before each state-changing step. user-invocable: true metadata: { "openclaw": { "emoji": "🏫" } } --- # OpenMAIC Skill Use this as a guided, confirmation-heavy SOP. Do not compress the whole setup into one reply and do not perform state-changing actions without explicit user confirmation. ## Core Rules - Move one phase at a time. - Before any state-changing action, ask for confirmation. - If local state already exists, show what you found and ask whether to keep it. - Do not assume the OpenClaw agent's own model or API key will be reused by OpenMAIC. - OpenMAIC classroom generation uses OpenMAIC server-side provider config. - This skill must not rely on any request-time model or provider overrides. - Only OpenMAIC server-side config files may control provider selection and defaults. - Do not default to asking the user to paste API keys into chat. - Prefer guiding the user to edit local config files themselves. - Do not offer to write API keys into config files on the user's behalf. - Once setup is complete and the user clearly asks to generate a classroom, do not ask for a second confirmation before submitting the generation job. - Keep confirmations for local file reads such as reading a PDF from disk. ## Optional Skill Config If present, read defaults from `~/.openclaw/openclaw.json` under: ```jsonc { "skills": { "entries": { "openmaic": { "enabled": true, "config": { "accessCode": "sk-xxx", "repoDir": "/path/to/OpenMAIC", "url": "http://localhost:3000" } } } } } ``` - If `accessCode` is present, default to hosted mode and skip the mode-selection prompt. - Use `repoDir` and `url` only as defaults for local mode. - Still confirm before acting. ## SOP Phases ### 0. Choose Mode First check skill config for `accessCode`. If present, announce that a stored access code was found and proceed directly to hosted mode (load [references/hosted-mode.md](references/hosted-mode.md), skip phases 1–4). Do not ask the user to paste the code again. If no `accessCode` in config, ask the user how they want to use OpenMAIC: 1. **Use hosted OpenMAIC** (recommended for quick start) — Requires an access code from open.maic.chat. No local setup needed. 2. **Run locally** — Clone the repo, configure provider keys, and run on your machine. If the user chooses hosted mode, load [references/hosted-mode.md](references/hosted-mode.md) and skip phases 1–4. If the user chooses local mode, proceed to phase 1 as usual. ### 1. Clone Or Reuse Existing Repo Load [references/clone.md](references/clone.md). Use this when the user has not installed OpenMAIC yet or when you need to confirm which local checkout to use. ### 2. Choose Startup Mode Load [references/startup-modes.md](references/startup-modes.md). Use this after the repo location is confirmed. Present the available startup modes, recommend one, and wait for the user's choice. ### 3. Configure Provider Keys Load [references/provider-keys.md](references/provider-keys.md). Use this before starting classroom generation. Recommend a provider path and tell the user exactly which config file to edit themselves. If generation later fails due to provider/model/auth issues, return to this phase and direct the user to update the same server-side config files. After the core LLM key is configured, ask the user if they want to enable optional features (web search, image generation, video generation, TTS). Each requires its own provider key — see the "Optional Features" section in provider-keys.md. ### 4. Start And Verify OpenMAIC After the user has chosen a startup mode and configured keys, start OpenMAIC using the chosen method, then verify the service with `GET {url}/api/health`. ### 5. Generate A Classroom Load [references/generate-flow.md](references/generate-flow.md). Use this only after the service is healthy. Confirm before reading local PDFs. If the user has already clearly asked to generate, do not ask for a second confirmation before submitting the generation job, and then follow the polling loop until it succeeds or fails. Only send the supported content fields for generation requests. For long-running jobs, prefer sparse polling and tell the user to check back later if the turn ends before completion. ## Response Style - Keep each step short and explicit. - Prefer 2-3 concrete options when the user must choose. - Always include the recommended option first and explain why in one sentence. - After a step completes, say what changed and what the next confirmation is for. - When returning a classroom link, place the raw absolute URL on its own line with no bold, markdown link syntax, code formatting, or tables.

path: references/clone.md
content: # Clone Or Reuse Existing Repo

## Goal

Establish which OpenMAIC checkout will be used for setup and runtime actions.

## Procedure

1. Check whether OpenMAIC already exists locally.
2. If a checkout exists, show the path and ask whether to reuse it.
3. If no checkout exists, propose cloning the repo and ask for confirmation.
4. After clone, confirm dependency installation separately.

## Recommended Path

- Recommended: reuse an existing checkout if it is already on the target branch.
- Otherwise: clone a fresh checkout from GitHub, then install dependencies.

## Commands

Clone:

```bash
git clone https://github.com/THU-MAIC/OpenMAIC.git
cd OpenMAIC
```

Install dependencies:

```bash
pnpm install
```

## Confirmation Requirements

- Ask before `git clone`.
- Ask before `pnpm install`.
- If the repo is dirty, tell the user and ask whether to continue with that checkout.


path: references/generate-flow.md
content: # Generate Flow

## Preconditions

- Repo path is confirmed
- Startup mode has been chosen
- OpenMAIC is healthy at the selected `url`
- Provider keys are configured

> **Hosted mode**: If using hosted OpenMAIC (open.maic.chat), all
> preconditions (repo, startup, provider keys) are already satisfied.
> Include `Authorization: Bearer <access-code>` header on all requests below.
> See [hosted-mode.md](hosted-mode.md) for details.

## Requirement-Only Generation

If the user has already clearly asked to generate the classroom and the preconditions are satisfied, submit the generation job immediately. Do not ask for a second confirmation just before calling `/api/generate-classroom`.

Submit the job with:

```text
POST {url}/api/generate-classroom
```

Request body:

```json
{
  "requirement": "Create an introductory classroom on quantum mechanics for high school students"
}
```

Only send supported content fields:

- `requirement` (required)
- optional `pdfContent`
- optional `language` (`"zh-CN"` | `"en-US"`, defaults to `"zh-CN"`) — any other value silently falls back to `"zh-CN"`
- optional `enableWebSearch` (boolean) — include web search context in outline generation
- optional `enableImageGeneration` (boolean) — allow image generation metadata in outlines
- optional `enableVideoGeneration` (boolean) — allow video generation metadata in outlines
- optional `enableTTS` (boolean) — enable server-side TTS audio generation for speech actions
- optional `agentMode` (`"default"` | `"generate"`) — controls agent profile strategy:
  - `"default"` (or omitted): uses built-in default agents
  - `"generate"`: uses LLM to generate custom agent profiles tailored to the course content

All optional boolean fields default to `false` when omitted. Omitting them preserves backward compatibility.

### Feature Detection

Before sending optional feature flags, query `GET {url}/api/health` and check the `capabilities` object:

```json
{
  "status": "ok",
  "version": "...",
  "capabilities": {
    "webSearch": true,
    "imageGeneration": false,
    "videoGeneration": false,
    "tts": true
  }
}
```

Only set a feature flag to `true` if the corresponding capability is `true`. If the server does not return `capabilities` (older version), do not send the new fields.

Do not rely on request-time model or provider override parameters.

Treat the `POST` response as job submission only. Expect fields such as:

```json
{
  "success": true,
  "jobId": "abc123",
  "status": "queued",
  "step": "queued",
  "pollUrl": "http://localhost:3000/api/generate-classroom/abc123",
  "pollIntervalMs": 5000
}
```

## PDF-Based Generation

1. Resolve the absolute path to the PDF.
2. Confirm before reading the file.
3. Parse the PDF first:

```text
POST {url}/api/parse-pdf
```

4. Then send `requirement` plus `pdfContent` to:

```text
POST {url}/api/generate-classroom
```

## Polling Loop

After the job is submitted:

1. Save `jobId`, `pollUrl`, and `pollIntervalMs`.
2. Do not submit another generation job while this one is still `queued` or `running`.
3. Poll:

```text
GET {pollUrl}
```

4. Prefer a conservative polling cadence of about 60 seconds between polls for classroom generation jobs, even if `pollIntervalMs` is shorter.
5. Treat `queued` and `running` as in-progress states.
6. Stop only when `status` becomes `succeeded` or `failed`.

### Reliability Rules

- Never restart the job just because a poll request fails once.
- If a poll request returns a transient network error or `5xx`, wait about 60 seconds and retry the same `pollUrl`.
- If the job is still running after many polls, tell the user it is still in progress and continue polling instead of resubmitting.
- Prefer fewer poll attempts over aggressive polling. Long-running jobs are more likely to survive agent-loop limits if the tool-call cadence stays low.
- Within a single agent turn, cap active polling to about 10 minutes. If the job is still not finished, tell the user it is still running and include the `jobId` and `pollUrl` so a later turn can continue checking without resubmitting.
- Report progress to the user only when `status`, `step`, or visible progress meaningfully changes. Do not spam every poll result.
- Do not try to recover from auth, provider, model, or base URL errors by changing request parameters. Tell the user to fix OpenMAIC server-side config and retry only after they confirm.
- On `failed`, surface the server error and include the `jobId`.
- On `succeeded`, use `result.classroomId` and `result.url` from the final poll response.

## If The Loop Ends First

If the job is still running when you stop active polling for this turn, tell the user that the classroom generation is still running in the background and invite them to come back a little later to continue checking the same job.

Use natural phrasing such as:

```text
The classroom generation is still running in the background.
Job ID: abc123

Check back with me in a little while and I can continue tracking this same job without starting over.
```

## What To Return

Return the generated classroom ID plus a directly clickable classroom URL.

Output the URL as a raw absolute URL on its own line.

Do not wrap the URL in:

- bold markers such as `**...**`
- markdown links such as `[title](url)`
- code formatting such as `` `...` ``
- angle brackets such as `<...>`
- markdown tables

Use a compact format like:

```text
Classroom ID: Uyh82Y32ZK
Classroom URL:
http://localhost:3001/classroom/Uyh82Y32ZK
```

If the job fails, return the job ID plus the server error.

If generation fails, surface the server error directly instead of paraphrasing it away.

If the error suggests a provider or model configuration problem, explicitly tell the user to update `.env.local` or `server-providers.yml` instead of attempting a runtime override.

## Confirmation Requirements

- Ask before reading a local PDF.
- Do not ask for a second confirmation before the generation request if the user has already clearly asked you to generate the classroom.


path: references/hosted-mode.md
content: # Hosted Mode

Use this when the user has an access code from open.maic.chat and wants to skip local setup.

## Access Code Setup

1. Read `accessCode` from skill config (`~/.openclaw/openclaw.json` → `skills.entries.openmaic.config.accessCode`).
2. If found, use it directly. Do not ask the user to paste the code into chat.
3. If not found, tell the user to add their access code to the config file:
   ```
   Edit ~/.openclaw/openclaw.json and set skills.entries.openmaic.config.accessCode to your access code (starts with sk-).
   ```
   Wait for the user to confirm before continuing. Do not ask them to paste the code in chat.
4. Verify connectivity: `GET https://open.maic.chat/api/health` with `Authorization: Bearer <access-code>`
   - On success: confirm connection and proceed to generation.
   - On failure (401): access code is invalid, ask the user to check or regenerate at open.maic.chat and update the config file.
   - On failure (network): suggest checking network or trying local mode.

## Generating a Classroom

Follow the same generation flow as [generate-flow.md](generate-flow.md) with these differences:

- **Base URL**: `https://open.maic.chat` (hardcoded, not configurable)
- **Authorization**: Include header `Authorization: Bearer <access-code>` on all API requests
- **Classroom URL**: `https://open.maic.chat/classroom/{id}`

### Feature Detection in Hosted Mode

Before generating, query `GET https://open.maic.chat/api/health` (with auth header) to check `capabilities`. Automatically include optional feature flags (`enableWebSearch`, `enableImageGeneration`, etc.) based on what the server supports. Do not send new fields if the server does not return `capabilities` (older version). This ensures forward compatibility — the hosted instance may update on a different schedule than the local codebase.

## Quota

- 10 generations per day, independent of web UI quota
- If generation returns 403 with `Daily quota exhausted`, inform the user of the daily limit and that it resets at midnight.

## Error Handling

| HTTP Status | Meaning | Action |
|-------------|---------|--------|
| 401 | Invalid access code | Ask user to check their code or generate a new one at open.maic.chat |
| 403 | Quota exhausted | Inform daily limit (10), suggest trying tomorrow |
| 500 | Server error | Suggest retrying later or switching to local mode |


path: references/provider-keys.md
content: # Provider Keys

## Critical Boundary

OpenMAIC generation does not automatically reuse the OpenClaw agent's current model or API key.

OpenMAIC server APIs resolve their own model and provider keys from OpenMAIC server-side config.

This skill does not rely on runtime overrides for model, provider, API key, base URL, or provider type.

If the user wants to change any of those, they must edit OpenMAIC server-side config files.

## Interaction Policy

- Do not begin by asking the user to paste an API key into chat.
- First, recommend a provider path.
- Then ask how the user wants to configure it.
- The user should edit `.env.local` or `server-providers.yml` themselves.
- Do not offer to write the key for them.
- Do not ask for the literal key in chat.
- Do not suggest temporary request-time overrides.
- If generation fails because of auth, provider, or model selection, direct the user back to server-side config files.

## Preferred User Flow

1. Recommend a provider option.
2. Ask where the user wants to configure it:
   - `.env.local` (recommended for most users)
   - `server-providers.yml`
3. Tell the user exactly which variables or YAML fields to edit.
4. Wait for the user to confirm they finished editing before continuing.

## Recommendation Paths

### 1. Lowest-Friction Setup

Recommended when the user wants the smallest amount of configuration.

Set:

```env
ANTHROPIC_API_KEY=sk-ant-...
```

Why:

- OpenMAIC server fallback is currently `gpt-4o-mini` if `DEFAULT_MODEL` is unset.
- If the user wants Anthropic or Google by default, they should set `DEFAULT_MODEL` explicitly.

### 2. Better Speed / Cost Balance

Recommended when the user is willing to set one extra variable.

Set:

```env
GOOGLE_API_KEY=...
DEFAULT_MODEL=google:gemini-3-flash-preview
```

Why:

- Good quality-to-speed balance
- Matches the repo's current recommendation direction better than the default fallback
- The `google:` prefix is important. Without a provider prefix, model parsing defaults to OpenAI.

### 3. Existing Provider Reuse

Use when the user already has OpenAI or another supported provider configured and wants to stick with it.

Examples:

```env
OPENAI_API_KEY=sk-...
DEFAULT_MODEL=openai:gpt-4o-mini
```

```env
DEEPSEEK_API_KEY=...
DEFAULT_MODEL=deepseek:deepseek-chat
```

## Model String Rule

When recommending or showing `DEFAULT_MODEL`, always include the provider prefix:

- `google:gemini-3-flash-preview`
- `anthropic:claude-3-5-haiku-20241022`
- `openai:gpt-4o-mini`
- `deepseek:deepseek-chat`

Do not recommend bare model IDs such as `gemini-3-flash-preview` by themselves, because OpenMAIC will otherwise parse them as OpenAI models.

Do not work around a wrong `DEFAULT_MODEL` by changing request parameters. The user should fix the server-side config instead.

## Preferred Config Method

For first setup, prefer `.env.local`:

```bash
cp .env.example .env.local
```

Then fill the chosen keys.

Alternative: `server-providers.yml`

```yaml
providers:
  anthropic:
    [REDACTED_SECRET]

  google:
    apiKey: ...

  openai:
    [REDACTED_SECRET]
```

If using a non-default provider for classroom generation, also set the model selection explicitly:

```env
DEFAULT_MODEL=google:gemini-3-flash-preview
```

## Recommended Prompts To The User

Preferred:

- "I recommend configuring OpenMAIC through `.env.local` first. Please edit that file locally and tell me when you're done."
- "For the simplest setup, I recommend Anthropic. For better speed/cost balance, I recommend Google plus `DEFAULT_MODEL=google:gemini-3-flash-preview`. Which path do you want?"

Avoid as the first move:

- "Send me your API key"
- "Paste your API key here"
- "Do you want me to write the key for you?"

## Confirmation Requirements

- Recommend one provider path first.
- Ask the user which config-file path they want.
- Instruct the user to modify the file themselves.
- Wait for the user to confirm they finished editing before continuing.
- Do not request the literal key.
- If provider/model/auth errors happen later, tell the user exactly which config entry to fix and wait for confirmation before retrying.

## Optional Features

These features require additional provider keys beyond the core LLM provider. Ask the user if they want to enable any of these after the core LLM key is configured.

| Feature | Env Variable(s) | Description |
|---------|-----------------|-------------|
| Web Search | `TAVILY_API_KEY` | Enriches outlines with real-time web research |
| Image Generation | `IMAGE_SEEDREAM_API_KEY`, `IMAGE_QWEN_IMAGE_API_KEY`, `IMAGE_NANO_BANANA_API_KEY` | Generates images for slides (any one suffices) |
| Video Generation | `VIDEO_SEEDANCE_API_KEY`, `VIDEO_KLING_API_KEY`, `VIDEO_VEO_API_KEY`, `VIDEO_SORA_API_KEY` | Generates short videos (any one suffices) |
| TTS | `TTS_OPENAI_API_KEY`, `TTS_AZURE_API_KEY`, `TTS_GLM_API_KEY`, `TTS_QWEN_API_KEY` | Text-to-speech narration (any one suffices) |

These are all optional. The classroom generation works without them — they only unlock richer content.

Alternatively, configure via `server-providers.yml`:

```yaml
web-search:
  tavily:
    [REDACTED_SECRET]

image:
  seedream:
    apiKey: ...

video:
  seedance:
    apiKey: ...

tts:
  openai-tts:
    [REDACTED_SECRET]
```


path: references/startup-modes.md
content: # Startup Modes

## Goal

Help the user choose how OpenMAIC should run before you start anything.

## Options

### 1. Development Mode

Recommended for first-time setup and debugging.

```bash
pnpm dev
```

Tradeoff:

- Fastest feedback loop
- Best for validating config changes
- Not representative of production startup

### 2. Production-Like Local Mode

Recommended when the user wants behavior closer to a deployed server.

```bash
pnpm build && pnpm start
```

Tradeoff:

- Closer to production
- Slower startup than `pnpm dev`

### 3. Docker Compose

Use only when the user explicitly wants containerized startup or wants to avoid local Node setup details.

```bash
docker compose up --build
```

Tradeoff:

- Cleaner isolation
- Heavier and slower
- Harder to debug application-level issues quickly

## Recommendation Order

1. `pnpm dev`
2. `pnpm build && pnpm start`
3. `docker compose up --build`

## Health Check

After startup, verify:

```bash
curl -fsS http://localhost:3000/api/health
```

If the skill config provides a custom `url`, use that instead.

## Confirmation Requirements

- Ask the user to choose one startup mode.
- Ask again before running the selected command.


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)