WMG Pte Ltd · Internal AI Developer Resource

Build the Agent Swarm that runs WMG

Everything you need to develop, deploy and maintain AI skills for the WMG MSA Agent Fleet. Read this before writing a single line of code.

Start Here Jump to Code

01 · Platform

How the WMG AI platform works

Before you write any skill code, you need to understand the three-layer stack that powers everything.

01

OpenClaw Gateway

The always-on Node.js process running on the VPS. It's the brain — managing sessions, routing messages, executing skills, and connecting to messaging platforms like WhatsApp.

02

Claude Haiku 4.5 (API)

The LLM that does the thinking. Your skill sends structured prompts to Haiku via the Anthropic API. Haiku reasons, classifies, drafts responses. Your skill acts on the output.

03

NemoClaw (OpenShell)

NVIDIA's security layer wrapped around OpenClaw. Enforces sandbox isolation, policy-based network access, and intent verification before any action executes.

04

Skills

JavaScript files you write that define what an agent can do. Skills are the only thing you directly build. Everything else is infrastructure.

You (Jim)
WhatsApp
MacBook Air
iPhone (Dispatch)
↓ approval gate — all actions reviewed
COO Layer
CORA · Chief Operations & Resource Administrator
↓ routes tasks to specialist agents
Phase 1
ARIA · Customer Service
MAX · Marketing
SUQI · Service Quality
Phase 2
CRAIG · Client Relations
HERA · HR
FINN · Finance
Phase 3
DEVI · Development
RITA · IT Operations
↓ all agents run on
Infrastructure
OpenClaw Gateway · VPS Singapore
NemoClaw · OpenShell Security
Claude Haiku 4.5 API
Tailscale · Private Network

02 · Agent Fleet

The WMG agent roster

Click any agent to see their full brief — tools, responsibilities, what they can and can't do, and which skills belong to them.


03 · Skill Structure

Anatomy of a WMG skill

Every skill is a folder with exactly four files. Understand what each one does before you start building.

📄 skill.json
Metadata, trigger type (schedule/event/manual), tools allowed, target agent, and LLM model. This is what OpenClaw reads to know when and how to run your skill.
⚙️ index.js
The main logic. Fetches data, calls the LLM, parses the response, takes action (send WhatsApp, update CRM, file report). This is the only file with actual JavaScript code.
📝 prompt.md
Plain English instructions that tell Claude Haiku how to reason about the task. Classification rules, output format, WMG-specific context. The most important file — get this right first.
🔧 config.json
WMG-specific settings: contact numbers, thresholds, key account lists, escalation rules. Keeps business logic out of code so non-developers can update it without touching index.js.
// skill.json — tells OpenClaw what this skill does and when to run it { "name": "wmg-email-triage", "version": "1.0.0", "description": "ARIA email triage for WMG Pte Ltd", "agent": "aria", // which agent this belongs to "trigger": { "type": "schedule", "cron": "*/30 * * * *" // runs every 30 minutes }, "tools": ["gmail", "whatsapp", "memory"], // ONLY list what you need "model": "claude-haiku-4-5", // always use Haiku unless approved otherwise "requires_approval": false, // set true for financial/HR/client actions "draft_and_approve": false // set true for outbound comms }
// index.js — the skill logic. Keep it clean and linear. const { getEmails, sendWhatsApp, memory } = require('@openclaw/tools'); const { readFile } = require('fs/promises'); const config = require('./config.json'); module.exports = async function run({ llm }) { // 1. FETCH — get the data const emails = await getEmails({ unread: true, since: '30m', maxResults: 20 }); if (emails.length === 0) return; // nothing to do — exit cleanly // 2. PROMPT — load instructions and ask Claude Haiku const prompt = await readFile('./prompt.md', 'utf8'); const result = await llm.complete({ System: prompt, user: emails.map(e => `FROM: ${e.from}\nSUBJECT: ${e.subject}\nSNIPPET: ${e.snippet}`).join('\n—\n') }); // 3. PARSE — extract what you need from the LLM response const urgent = JSON.parse(result).filter(e => e.priority === 'URGENT'); // 4. ACT — take action (always wrap in try/catch) try { if (urgent.length > 0) { await sendWhatsApp({ to: config.jim_whatsapp, message: formatSummary(urgent) }); } await memory.set('aria.last_triage', new Date().toISOString()); } catch (err) { // 5. ERROR HANDLING — always notify CORA, never crash silently await notifyCORA({ agent: 'ARIA', skill: 'wmg-email-triage', error: err.message }); } };
# prompt.md — plain English instructions for Claude Haiku # This is the most important file. Spend the most time here. You are ARIA, WMG Pte Ltd's customer service agent. WMG is a Singapore-based logistics company. Analyse each email and classify it as URGENT or ROUTINE. ## URGENT if any of these apply: - Client complaint or escalation about service failure - Shipment delay, customs hold, or cargo issue - Payment dispute or invoice overdue by 30+ days - Request from a named key account (see config for list) - Explicit deadline mentioned within 24 hours ## ROUTINE if: - General enquiry answerable within 24 hours - Newsletter, marketing, or automated notification - Internal FYI with no action required ## Rules: - When in doubt, classify as URGENT - Never suggest actions that involve committing WMG funds - Always recommend escalation for legal or compliance matters ## Output format — JSON array only, no other text: [{"id": "…", "priority": "URGENT|ROUTINE", "reason": "one line max", "suggested_action": "…"}]
// config.json — business settings, not code logic // Non-developers should be able to update this safely { "jim_whatsapp": "+65XXXXXXXX", "key_accounts": [ "Evergreen Shipping", "PT Maju Logistics", "Sinotrans" ], "escalation_threshold_days": 30, "urgent_keywords": ["customs hold", "cargo damage", "missed deadline"], "working_hours_sg": { "start": 8, "end": 18 }, "silent_hours_notify": false, // don't WhatsApp Jim between 10pm-7am "dry_run": false // set true during testing }

04 · Coding Standards

WMG skill coding standards

These are non-negotiable. Every skill merged to production must follow all of these.

🔒
Least privilege tools
Only declare the tools your skill actually uses in skill.json. If ARIA's triage skill needs Gmail and WhatsApp, list only those — not filesystem, not browser, not shell.

DO: ["gmail","whatsapp"] DON'T: ["*"] or ["shell"]
🛡️
Always catch errors
Every skill must have a try/catch around the ACT phase. On catch, notify CORA with agent name, skill name, and error message. Never let a skill fail silently.

DO: notifyCORA on catch DON'T: silent failures
Draft-and-approve for comms
Any skill that sends messages to clients, partners, or external parties must set "draft_and_approve": true. Jim reviews the draft before it sends. No exceptions for external comms.

Client email → draft first Internal only → can auto-send
🚫
No financial actions
No skill may initiate, approve, or commit any financial transaction. FINN may draft payment summaries and flag overdue invoices — but never trigger payment. Always requires_approval: true.

Never trigger payments Draft + flag only
🧪
Dry-run before enabling
All new skills must pass a dry-run on the iMac dev environment before deployment to the VPS. Set dry_run: true in config.json, review output, then flip to false for production.

iMac → dry-run → VPS Never skip dry-run
📝
Prompt-first development
Write prompt.md before index.js. Test the prompt manually in Claude.ai with sample data. Only start coding once the LLM output is exactly what you need. Bad prompts waste engineering time.

prompt.md first Don't code before prompting
💰
Use Haiku, justify Sonnet
All skills default to claude-haiku-4-5. If you believe a task requires Sonnet (complex reasoning, multi-document analysis), document why in a PR comment and get approval before deploying.

Default: Haiku Sonnet: needs approval
🧱
One skill, one job
Each skill file does exactly one thing. Email triage is one skill. WhatsApp reply is another. SLA monitoring is another. Don't combine multiple functions — it makes debugging impossible.

One responsibility No multi-function skills

05 · Dev Workflow

How to build and ship a skill

Follow this exact sequence every time. No shortcuts.

1
Get a brief from CORA
Every skill starts with a written brief: which agent, what trigger, what tools, what output. If you don't have a brief, ask for one before writing anything.
2
Write and test prompt.md first
Open Claude.ai. Paste 5–10 realistic sample inputs. Iterate the prompt until the output JSON is exactly right. Save all test cases — you'll need them later.
Test in claude.ai before touching code
3
Create the skill folder on iMac
Work locally on your iMac M1 dev machine. Create the four files. Set dry_run: true in config.json. Never develop directly on the VPS.
~/.openclaw/skills/wmg-[agentname]-[function]/
4
Dry-run on iMac
Install and run the skill locally. Review every line of output. Check what would have been sent, filed, or actioned. Fix any issues before proceeding.
openclaw skills install [name] && openclaw skills run [name] --dry-run
5
Push to VPS via Tailscale
Once dry-run is clean, copy the skill to the VPS production gateway. Set dry_run: false only after a second dry-run on the VPS confirms everything.
scp -r ./skill-folder wmg@100.x.x.x:~/.openclaw/skills/
6
Add to NemoClaw policy
Every new skill must be added to the OpenShell allowlist with only the network endpoints it needs. Skills not in the policy file will not run.
Edit ~/.openclaw/nemoclaw-policy.yaml → add skill + allowed endpoints
7
Enable and monitor
Enable the skill on the VPS. Watch the first 3 live runs in the dashboard. Check logs. Confirm CORA receives correct output. Only then mark it as production-stable.
openclaw skills enable [name] && tail -f /tmp/openclaw/openclaw-*.log

06 · Quick Reference

The rules at a glance

Print this. Stick it on your wall. Follow it every time.

✅ Write prompt.md before index.js — always ✅ Test with 10+ real sample inputs before shipping ✅ Set dry_run: true until you've seen 3 clean dry-runs ✅ Catch all errors and notify CORA ✅ Use claude-haiku-4-5 as default model ✅ Add every skill to NemoClaw policy before enabling ✅ Use draft_and_approve: true for all external comms ✅ Keep config.json for business settings (thresholds, names, numbers) ✅ Log what the skill did to memory after each run ✅ One skill = one job, named after what it does
🚫 Never deploy directly to VPS without dry-run on iMac first 🚫 Never use wildcard tools: ["*"] in skill.json 🚫 Never trigger financial transactions — draft only 🚫 Never hardcode API keys, tokens, or passwords in skill files 🚫 Never use shell tool unless explicitly approved by Jim 🚫 Never send external comms without draft_and_approve: true 🚫 Never use Sonnet model without written approval 🚫 Never combine two functions into one skill file 🚫 Never skip the NemoClaw policy step 🚫 Never fail silently — always catch and report to CORA
CORA Chief Operations & Resource Administrator · orchestration + KPI oversight Tools: all agents, memory, reporting · Phase: always-on ARIA Automated Response & Intelligence Assistant · customer service Tools: gmail, whatsapp, memory · Phase 1 MAX Marketing Automation & eXecution · marketing manager Tools: gmail, web_search, memory · Phase 1 SUQI Service & Quality Intelligence · service quality Tools: memory, reporting, whatsapp · Phase 1 CRAIG Client Relations & Account Intelligence Guide · CRM Tools: gmail, whatsapp, crm, memory · Phase 2 HERA Human Resources Engagement & Records Administrator · HR Tools: gmail, memory, calendar · Phase 2 · requires_approval: true FINN Financial Intelligence & Numerical Navigator · finance Tools: gmail, memory, reporting · Phase 2 · requires_approval: true ALWAYS DEVI Development & Engineering Virtual Intelligence · software dev Tools: shell (approved), github, memory · Phase 3 RITA Remote IT & Technology Administrator · IT ops Tools: shell (approved), monitoring, memory · Phase 3
# Skill folder naming convention wmg-[agent]-[function] # Examples wmg-aria-email-triage ← ARIA, email triage function wmg-aria-whatsapp-reply ← ARIA, WhatsApp auto-reply wmg-finn-invoice-monitor ← FINN, invoice monitoring wmg-suqi-sla-alert ← SUQI, SLA breach alerting wmg-cora-health-check ← CORA, swarm health check wmg-craig-crm-update ← CRAIG, CRM record update # Function naming in index.js — verb-noun format fetchUnreadEmails() classifyUrgency() sendWhatsAppAlert() updateMemory() notifyCORA() # Branch naming for skill development skill/wmg-aria-email-triage skill/wmg-finn-invoice-monitor