OpenClaw is an open-source AI agent gateway. You provision agents, bind them to channels like Discord, the web, and Telegram, and route their tool access through a local runtime. I used it to build Subydoo, a multi-agent support system for N3D Melbourne, a one-person 3D modeling design studio with nearly 300 models, subscription tiers, and an active Discord community.

Subydoo is an orchestrator with specialist sub-agents. Between them they cover the departments a growing business would normally hire for: customer support, billing and accounting, application engineering, print troubleshooting, content administration, and community moderation. Each role is a purpose-built agent with scoped memory, tool access, and domain knowledge, and together they handle the operational load of a business that would otherwise need five or six people.

The triage algorithm

Every ticket gets scored on two axes: confidence (how sure the agent is about the answer) and risk (what happens if the answer is wrong). Those two scores decide whether the ticket is handled automatically, queued for my review, or escalated to a human.

triage-scoring.js
// Risk x Confidence scoring for ticket triageconst triageTicket = (ticket) => {  const confidence = scoreConfidence(ticket);  // 0-100  const risk       = assessRisk(ticket);       // low | medium | high  // High confidence + low risk = auto-send  if (confidence > 85 && risk === 'low')    return { action: 'auto_send', review: false };  // Medium confidence or risk = admin review  if (confidence > 50 || risk === 'medium')    return { action: 'draft_ready', review: true };  // Low confidence or high risk = human escalation  return { action: 'needs_escalation', review: true };};

Risk assessment scans for chargeback and dispute keywords, checks whether the ticket touches financial data, and flags anything that could change an account. Billing disputes and account merges always go to a human, regardless of confidence.

Stripe MCP integration

The orchestrator talks to Stripe through MCP (Model Context Protocol) tools, for reads and for writes. It can look up subscription status, payment history, and invoice details. I also gave it scoped write access for the cases where the right action is obvious: refunding a customer who hasn’t downloaded a single design, swapping a subscription to the correct price ID when someone was charged wrong, or moving a payment method from Stripe to PayPal when a price mismatch is detected. The risk score gates which of those can fire automatically and which need a human first.

stripe-mcp-actions.js
// Scoped Stripe write actions gated by risk scoringconst billingActions = {  // Auto-refund: customer never downloaded anything  refund: (invoice) =>    invoice.downloads === 0 && stripe.refund(invoice.id),  // Swap subscription to correct price ID  swapPrice: (sub, correctId) =>    stripe.updateSubscription(sub.id, { price: correctId }),  // Switch provider when price mismatch detected  switchToPaypal: (customer) =>    paypal.createSubscription(customer.email, customer.plan),};

I’ve demoed this integration to Stripe’s engineering team.

How the orchestrator works

The orchestrator is bound to several channels and changes its behavior depending on where it is.

Web portal tickets

Tickets from the website get enriched with membership data, linked accounts, and subscription history. The orchestrator has authenticated read-only access to Supabase through MCP for user lookups, account details, billing records, feature entitlements, and download logs. It scores the ticket on risk and confidence, then either auto-sends a response (including Stripe write actions like refunds or subscription swaps), queues a draft for my review, or delegates to a specialist.

Admin Discord channels

In the private admin channels it switches into an inner-circle mode: casual banter, Australian slang, the the occasional roast. This mode runs on Kimi Turbo, which is quick and cheap enough for chat.

Public Discord channels

In customer-facing channels the tone is professional and warm. It answers questions, links to resources, and escalates when it should.

Moderator-invoked actions

Mods trigger specific actions through commands: create a support ticket from a Discord thread and ask the user for the details it needs, push non-destructive content fixes to the website like correcting a design description, or flag and time out abusive users with automatic restriction emails.

Cron jobs and background tasks

Several jobs run on a schedule with no human trigger. A heartbeat sweep polls every 15 minutes for unresolved tickets and catches anything that slipped through. A web ticket poller watches Supabase for new contact-form submissions and routes them into the orchestrator. Discord role sync keeps membership tiers aligned between the website and the server. Memory sync propagates knowledge updates from the canonical workspace to every specialist mirror. The eval suite can also run on a schedule to regression-test the whole system.

Specialist sub-agent architecture

The core design rule is that the orchestrator should not try to be an expert at everything. It classifies the ticket’s domain and delegates to a specialist. Each specialist has its own workspace, its own bootstrap prompt, and a read-only mirror of the canonical memory store. One sync script pushes knowledge updates from the parent to every specialist.

agent-delegation.js
// OpenClaw specialist sub-agent routingconst specialists = {  billing:  { model: 'minimax-m3',  scope: 'accounts, payments, tiers' },  print:    { model: 'minimax-m3',  scope: '3D print troubleshooting' },  web:      { model: 'minimax-m3',  scope: 'website bugs, platform' },  dev:      { model: 'kimi-coding', scope: 'code changes, N3D codebase' },};// Each specialist gets read-only memory mirrors// synced from the canonical parent workspace://   workspace-discord/memory/  (canonical)//     -> workspace-discord-billing/memory///     -> workspace-discord-print/memory///     -> workspace-discord-web/memory///     -> workspace-discord-dev/memory/const delegate = (domain, ticket) =>  spawnAgent(specialists[domain], ticket);

Each specialist is scoped to its domain with isolated memory and restricted tool access, which keeps each agent’s knowledge surface narrow and reduces halucination.

specialist-routing.sh
# Orchestrator classifies domain, delegates to specialistclassify(ticket.domain)  ├─ billing  ──▶ MiniMax M3     // Stripe + PayPal MCP, entitlements, refunds  ├─ print    ──▶ MiniMax M3     // filament profiles, temps, layer adhesion  ├─ web      ──▶ MiniMax M3     // platform bugs, OAuth, downloads  └─ dev      ──▶ Kimi (coding)  // full codebase, opens PRs (review only)# All specialists share read-only memory mirrors# synced from canonical parent via sync-specialist-memory.sh

The dev agent is worth describing on its own. When a ticket needs a code change, the dev specialist (running Kimi’s coding model) has full access to the N3D codebase. It investigates, writes a fix, and opens a pull request for me to review. It cannot merge, deploy, or message customers, and a human always reviews the PR before anything ships.

The current model split is MiniMax M3 for anything that calls tools, Kimi’s coding model for the dev agent, and Kimi Turbo for chat. At the first model shootout, MiniMax M2.7 scored 94% on the eval suite against 85.7% for GPT-4.1, and production has since moved to M3. The whole setup runs on roughly $20 a month in LLM costs.

~90%
Tickets auto-resolved
94%
Eval score at the first shootout (MiniMax M2.7)
~$20
Monthly LLM spend

The layer above Subydoo

More recently I added an orchestrator above Subydoo: a personal assistant that handles my own tasks and can hand work down to Subydoo, which delegates to its specialists in turn. Each tier has a narrower job than the one above it.

delegation-tiers.sh
# Three tiers of delegationassistant                 # my own tasks  └─ subydoo            # N3D operations       └─ specialists   # billing / print / web / dev

Advice for building these

Two things I’d tell anyone building a system like this. First, lint everything: prompts, workspace files, tool configs, memory docs. If a script can check it, check it before an agent reads it. Second, make hard rules. Anything that matters, like which Stripe actions can fire without review, belongs in a code-level gate rather than a sentence in a prompt, because an agent can drift on a guideline and can’t drift on a gate.

Why this matters

As a business grows it needs more than support staff: billing people, community managers, application engineers, content admins, QA. Each of those is a hire, a salary, onboarding, and management overhead, and for a solo founder that wall is where growth stalls.

Subydoo absorbs the operational volume that would otherwise force premature hiring. The hard 10% still lands with a person, with full context, history, and a drafted resolution attached.

One person now runs a business with nearly 300 products, several subscription tiers, commercial licensing, a seller ecosystem, and an active community without support staff, a billing department, or a community manager.