Patterns and templates for building robust multi-agent systems with OpenClaw.
Why This Skill Is Complex (Read Before Installing)
This is one of the most feature-dense skills in the ClawHub registry. Security scanners will flag it — not because it's malicious, but because it does a lot. Here's exactly what's in it and why:
Scope:
4 production-ready JS libraries (~1,200 lines total across spawn-security-proxy, spawn-researcher, cost-estimator, quality-scorer)
A setup.sh that creates local directory scaffolding (no network calls, no package installs)
Inline attack vector documentation in spawn-security-proxy.js (test fixtures, not live payloads)
Why the libs exist: These aren't glue code — they implement real patterns: output sanitization with canary tokens, multi-source research validation, cost projection with approval gates, and subagent output scoring. The complexity is the point; simpler skills don't solve these problems.
Why scanners flag it:
JS code in a skill package looks like an execution surface — it is, but only when you explicitly require() it
The security proxy documents injection attack patterns as test examples — pattern matchers don't distinguish documentation from intent
External integration references (Discord, peer agents) appear in templates — they're opt-in workflows, not auto-configured connections
Complexity is not a red flag here. It's the product.
⚠️ Security Transparency Notice
What this skill contains:
lib/ — Reference JS libraries (spawn helpers, cost estimator, quality scorer). These are not auto-executed. Copy them to your workspace lib/ directory to use them.
templates/ — Markdown spawn templates for common patterns.
setup.sh — Creates local directory scaffolding only. Makes no network calls, installs no packages.
External integrations: All optional, none auto-configured.
Discord webhooks — Only used in the federated peer-review pattern. You supply your own token manually. This skill does not store or transmit credentials.
Peer agent endpoints — Federated review is opt-in. No external calls unless you explicitly configure peer URLs.
Credential requirements: None. No API keys, tokens, or env vars are required or auto-read by this skill.
Overview
This skill provides battle-tested patterns for:
Security isolation - Contain high-risk operations with minimal context exposure
Specialized research - Multi-perspective data gathering with domain experts
Phased implementation - Architecture → Development → Review pipelines
Peer collaboration - External validation via federated agent network (opt-in)
Cost-aware spawning - Budget estimation and optimization strategies
task-routing skill (auto-classification and routing)
cost-governor (budget enforcement)
drift-guard (behavioral validation)
Quick Start
1. Install Skill Structure
bash
cd $OPENCLAW_WORKSPACE/skills/subagent-architecture
bash setup.sh # Creates directories and scaffolding
2. Choose Your Pattern
For high-risk operations:
bash
# Read security-proxy template
cat templates/security-proxy.md
# Spawn isolated proxy for untrusted API
# (see template for full example)
For research tasks:
bash
# Read researcher-specialist template
cat templates/researcher-specialist.md
# Spawn domain expert for deep analysis
# (see template for multi-perspective pattern)
For complex features:
bash
# Read phased-implementation template
cat templates/phased-implementation.md
# Launch architect → coder → reviewer pipeline
# (see template for orchestration example)
For external validation:
bash
# Read peer-review-specialist template
cat templates/peer-review-specialist.md
# Request peer agent review via Discord/API
# (see template for federated trust protocol)
Agent Registry: AGENTS.md is Optional
Critical clarification for new users: AGENTS.md is a human-readable reference document, not a configuration file. The spawning system does not read it.
How spawning actually works
sessions_spawn is a tool call — it takes parameters you provide at the moment of the call. It does not read from any file, config, or registry. You can spawn subagents on a completely fresh OpenClaw install with zero files in your workspace.
javascript
// This is ALL the system needs — no AGENTS.md required
sessions_spawn({
label: "my-researcher",
task: "Research the topic X",
model: "sonnet"
})
What AGENTS.md actually is
AGENTS.md (and domain files like AGENTS_WRITING.md, AGENTS_INFRA.md) are memory aids for you (the agent). They store:
Agent names and personality snippets you've found effective
Cost history and last-used dates
Notes on what tasks each agent type handles well
You can split AGENTS.md into 50 domain files or delete it entirely — spawning still works. The split is purely for your readability; it has zero functional effect.
What "read AGENTS_WRITING.md before spawning" means
When documentation says "read AGENTS_WRITING.md before spawning AuthorAgent", it means:
Read it so you know what personality, model, and task description to use when building the spawn call.
The system does not read it. You read it, extract the configuration, then make the spawn call with those parameters.
Practical implication for fresh installs
When you install this skill on a fresh OpenClaw setup:
You do not need to create AGENTS.md to use subagents
Start spawning immediately with inline parameters
Create AGENTS.md when you have enough recurring agent configurations that you want a reference doc
Split into domain files when AGENTS.md grows beyond ~10 entries and becomes hard to scan
See templates/agents-registry-template.md for a minimal starter template when you're ready.
Reference Implementations
NEW in v2.1: Production-ready code libraries for all patterns.
Path Resolution Note: The require() paths in examples below assume you call them from your workspace root. If you call from within the skill directory (e.g., inside an example script), use __dirname instead. For portable code that works regardless of cwd:
javascript
// Path resolution — works regardless of workspace structure
const path = require('path');
const SKILL_DIR = __dirname; // when called from within skill directory
// OR if calling from workspace root:
const SKILL_DIR = path.join(process.env.OPENCLAW_WORKSPACE || process.cwd(), 'skills', 'subagent-architecture');
const { spawnSecurityProxy } = require(path.join(SKILL_DIR, 'lib', 'spawn-security-proxy'));
Main Agent (full context)
│
└─ SecurityProxy (minimal context)
├─ Query: "Get weather for New York"
├─ Tools: exec (curl only)
├─ Output: Sanitized JSON (no API metadata)
└─ Auto-terminate after single task
Key principles:
Minimal context (only task parameters, no workspace paths)
Tool restrictions (whitelist, not blacklist)
Output sanitization (validate schema before returning)
Reciprocal reviews (offer your expertise to peers)
Cost-effective (free peer reviews vs paid audits)
⚠️ Trust tier ≠ security bypass:
If you implement tiered trust (Acquaintance → Friend → Ally or equivalent), "higher trust" means relaxed engagement policy — not skipping security validation. Content from even the most trusted peer still goes through injection detection (Stage 4). An ally account can be compromised; the injection scanner is the last defense that can't be socially engineered. "Light validation" always means reduced schema scrutiny, never reduced security scanning.
Problem: Security proxies are ephemeral (spawn-per-task, terminate). But some external services require a persistent identity — a social network account, an API user, a recurring agent persona. These are in tension.
Solution: Separate the process lifecycle from the external identity. The process dies every spawn. The external identity persists through workspace state + core-managed credentials.
text
External service sees: CedarProxy (consistent identity across all spawns)
Under the hood:
Spawn 1: [process starts] → reads state files → executes → [process dies]
Spawn 2: [new process] → reads same state files → continues → [dies]
Spawn 3: [new process] → reads same state files → continues → [dies]
State that persists: /proxy-workspace/ files (logs, relationships, posts)
State that doesn't: in-memory session, conversation history, token
Credentials: held by core, passed as short-lived scoped token at spawn time
Key rules:
Credentials live in core memory only — never in proxy workspace files
Session token: short TTL (2 hours max), passed encrypted in task context, never written to disk
Consistency: core injects "recent context" summary (last N interactions) into each spawn's task description so the new process knows what prior spawns committed to
Token rotation: scheduled by core (e.g., weekly), not the proxy
Anti-pattern: storing tokens in [workspace]/config.json — if the proxy workspace is compromised, credentials should not be compromised with it.
6. Research Team (Parallel Multi-Lens Analysis)
Problem: Single-agent analysis has blind spots — the same agent proposes and evaluates its own ideas.
Solution: Spawn 3 specialist agents in parallel with distinct analytical lenses, then synthesize into one unified response.
buildUnifierTask(query, sessionId) — builds synthesis prompt from chatroom
checkLensCompletion(sessionId) — verifies all lenses posted before unifying
Lens discipline:
Each lens gets a distinct role description injected into its prompt
Lenses do NOT communicate with each other — only through the chatroom
UnifierAgent reads all lens outputs and produces ONE response
If a lens fails silently, UnifierAgent warns but synthesizes from available data
Cost: ~4x single-agent. Gate on complexity to control spend.
Critical rule: Grok or any external model used as a lens is a leaf node — it answers, it never spawns further agents.
See: lib/research-coordinator.js for reference implementation.
7. External Model Consultation
Problem: Your agent may have architectural blind spots that another model's reasoning style would catch. Human relay (copy/paste to another AI) is slow and lossy.
Solution: Spawn an ExternalConsultAgent subagent that calls an external model's API directly, persists the session, and returns the response.
Why subagent, not core agent:
External API calls are side effects with cost and data exposure implications. Isolating them in a subagent follows the blast-shield philosophy — if something goes wrong, it's contained.
Last consultation > 24 hours ago (with lock file to prevent race conditions)
Security rules (enforce before go-live):
External model is a leaf node — never triggers further spawns
Context sanitization before every call — strip API keys, file contents, internal paths
Session-level call cap (prevent fan-out)
Metadata logging of every call (timestamp, provider, trigger reason)
Key stored in environment variable, not config file
Session continuity:
Pass sessionId from a previous consultation to continue the conversation. The bridge injects prior message history automatically.
See: lib/external-bridge.js for reference implementation.
8. Intent Engineering (Value Alignment over Time)
Problem: Prompt engineering tells agents what to do. Context engineering tells agents what to know. Neither tells agents what to want — so they drift from user values over time without detection.
Solution: A three-layer system that encodes agent intent, extracts intent signals from user behavior, and detects drift before it becomes a problem.
Three layers:
Intent Manifest (memory/intent-manifest.json) — Machine-readable intent spec per agent: core purpose, hard constraints (with regex), operational goals with verification keywords, user signals extracted from history
Intent Extractor (lib/intent-extractor.js) — Weekly pass over episode history extracting preference/value/correction signals; decays old signals (rate: 0.975/week), prunes below 0.30 strength
Drift Detector (lib/intent-drift-detector.js) — 5-component score per episode: hard constraint violations (0.35), goal keyword coverage (0.25), structural drift via Jaccard (0.20), correction pressure (0.15), forbidden phrase hits (0.05)
Drift levels:
GREEN (< 0.29): Normal operation
YELLOW (0.29–0.48): Inject reminder next turn
ORANGE (0.48–0.68): Log + prepare summary
RED (≥ 0.68): Flag for user check-in (triggers auto-consult gate)
Auto-route to pattern (security-proxy, researcher, phased-impl)
Cost governor:
Pre-spawn approval for expensive operations
Budget tracking per project/feature
Alert on overruns
Drift guard:
Behavioral audit of subagent outputs
Policy violation detection
Quality score trending
Framework Limitations & v2 Roadmap
Known gaps identified in peer review (Agent Smith, EasyClaw project)
Current OpenClaw subagent framework has architectural limitations that affect all patterns in this skill. These are framework-level constraints, not skill-specific issues. Documenting for transparency and future improvement.
1. Spawn Configuration Constraints
Smith's Question:"How does core define sub-bot constraints before launch?"
// Proposed: Skill capability manifest
// skills/my-skill/SKILL.md
---
capabilities_required:
- web_search # Skill needs web access
- read:config/ # Can read config directory only
- write:output/ # Can write to output directory only
isolation_level: sandbox # Run in isolated context
max_execution_time: 30 # Kill after 30 seconds
---
// Runtime: Skill runs in sandbox with only declared capabilities
// Attempts to use undeclared tools → blocked, logged, skill terminated
Impact on Patterns:
Security proxy: Skills could be sandboxed (currently rely on manual isolation)
All patterns: Skills loaded by subagents would inherit spawn constraints
Peer review: External skills from peers could run safely (sandboxed)
3. Communication Bounds (Bidirectional Channel)
Smith's Question:"What can sub-bots ask for from core?"
Current State:
One-way communication only: Core spawns → Subagent executes → Returns result
Subagent cannot request clarification mid-task
Subagent cannot request additional context during execution
No interactive mode
Limitations:
❌ Subagent stuck on ambiguous requirement → Must guess or fail
❌ Subagent needs additional context → Can't ask, works with what it has
❌ Subagent encounters unexpected scenario → No escalation path mid-task
❌ Human approval needed mid-execution → Not possible (only pre/post spawn)
Current Workaround:
Over-specify context in initial spawn (bloated prompts)
Subagent makes best guess (may be wrong)
Subagent fails, core respawns with clarification (expensive)
v2 Design Considerations:
javascript
// Proposed: Request-response protocol during execution
// Subagent code:
const clarification = await requestFromCore({
type: "clarification",
question: "User said 'recent data' - how many days back?",
options: ["7 days", "30 days", "90 days"],
timeout_seconds: 60 // If no response, default to first option
})
// Core receives request:
// - Auto-approve safe requests (data lookup from memory)
// - Escalate to human for decisions
// - Return answer to subagent
// - Subagent continues with clarification
// Examples:
// - "Need API key for service X" → Core provides from secure store
// - "Found conflicting data, which source to trust?" → Human decides
// - "Task seems too expensive ($5 estimated), proceed?" → Approval workflow
Impact on Patterns:
Researcher: Can ask "should I dig deeper on this tangent?" mid-research
Phased impl: Coder can ask architect for design clarification during build
Security proxy: Can request human approval if API returns unexpected data
All patterns: Reduces over-specification, enables adaptive execution
4. Termination Conditions (Resource-Based Kills)
Smith's Question:"When does core kill a sub-bot?"
Current State:
Time-based only: Timeout (specified in spawn) or task completion
Manual intervention (human stops runaway agent)
No automatic resource-based termination
Limitations:
❌ No memory limit kills (agent can OOM the host)
❌ No cost threshold kills (can exceed budget before timeout)
❌ No stuck detection (infinite loops run until timeout)
❌ No output size limits (can generate gigabytes of text)
Current Workaround:
Set conservative timeouts (may kill productive work early)
Monitor logs manually (reactive, not proactive)
Hope agent doesn't get stuck in expensive loop
v2 Design Considerations:
javascript
// Proposed: Multi-condition termination
spawnSubagent({
label: "researcher-x",
task: "Research topic",
termination: {
// Existing
timeout_minutes: 20,
// New: Resource limits
max_memory_mb: 512, // Kill if RSS > 512MB
max_cost_usd: 1.00, // Kill if projected cost > $1
max_output_tokens: 10000, // Kill if response > 10k tokens
// New: Behavioral detection
stuck_detection: {
enabled: true,
same_action_threshold: 5, // Kill if repeats same tool call 5x
no_progress_minutes: 5 // Kill if no new output for 5min
},
// New: External triggers
kill_signal: "session:parent_terminated" // Kill if parent agent dies
}
})
// Termination reasons logged for analysis:
// - "timeout" (existing)
// - "memory_exceeded" (new)
// - "cost_exceeded" (new)
// - "stuck_loop_detected" (new)
// - "output_overflow" (new)
// - "parent_died" (new)
Note for users:
These limitations affect all subagent patterns in this skill. The patterns documented here (security-proxy, researcher, phased-impl, peer-review) work within current framework constraints. v2 improvements would enhance safety and reliability, but are not required for effective use of these patterns today.
Tracking: OpenClaw framework issue (conceptual - not filed yet)
Credit: Agent Smith (EasyClaw peer review, 2026-02-22)
Examples
Example 1: Security-First API Integration
Scenario: Integrate with untrusted social network API
javascript
// Main agent receives request
const task = "Fetch user's posts from SocialNetworkX API"
// Security proxy pattern
const proxy = await spawnSubagent({
label: "proxy-socialnetworkx",
pattern: "security-proxy",
task: "Query SocialNetworkX API for user posts, return sanitized JSON",
context: {
query: "user:$USERNAME, limit:10"
// NO API keys, NO workspace paths
},
tools_allowed: ["exec:curl"],
timeout_minutes: 5,
auto_terminate: true
})
// proxy returns: [{username, timestamp, content}] - sanitized
// Main agent: Safe to process, no raw API exposure
Architect plan unrealistic (coder can't implement)
Coder deviated from plan (reviewer rejects)
Reviewer too strict (perfect is enemy of good)
Solutions:
Architect: Include feasibility check (can this be built?)
Coder: Flag deviations early (request plan amendment)
Reviewer: Focus on critical issues (don't block on style)
Problem: Peer review unavailable or slow
Diagnosis:
Peer bot offline or rate-limited
No trusted peers for required domain
Review package too large or unclear
Solutions:
Maintain backup peer list (2+ per domain)
Fall back to internal review (DevOps, CoderAgent)
Simplify review package (focus on specific question)
Framework Limitations & v2 Roadmap
Known gaps identified in peer review (Agent Smith, EasyClaw - 2026-02-22)
These limitations represent areas where the current OpenClaw subagent framework needs evolution. Documented here for transparency and future development.
Impact: Without per-spawn constraints, one rogue subagent can exhaust resources for all others.
2. Skill Loading - Runtime Validation
Current state:
External skills: Pre-execution vetting via skill-vetter (red flag detection)
Internal skills: Trusted by default, no runtime sandboxing
Missing:
Runtime sandboxing for skill-embedded code (JavaScript, shell scripts)
Execution validation (verify skill behaves as documented)
Resource monitoring during skill execution
v2 Design Consideration:
javascript
// Sandbox wrapper for skill execution
runSkill('ai-writing-humanizer', {
sandbox: {
networkAccess: false, // Block network except allowlisted domains
filesystemAccess: 'readonly', // Read-only except explicit write paths
cpuLimit: '50%', // Prevent CPU monopolization
timeout: 30000 // 30s max execution
},
validate: {
outputSchema: { ... }, // Verify output format
sideEffects: ['writes to /workspace/humanizer/'], // Allowed side effects
noExternalCalls: true // Flag if skill attempts network/exec
}
})
Impact: Without runtime sandboxing, malicious or buggy skills can compromise core agent.
3. Communication Bounds - Bidirectional Channels
Current state:
One-way communication only: Core spawns → Subagent executes → Result returns
Subagents cannot ask clarifying questions during execution
Missing:
Mid-task clarification requests ("Should I proceed with risky operation?")
Progress updates for long-running tasks (>5min execution)
Dynamic priority adjustment (core can signal "abort" or "expedite")
v2 Design Consideration:
javascript
// Subagent perspective
async function executeTask(taskDescription) {
const plan = generatePlan(taskDescription);
if (plan.hasHighRiskOperation()) {
const approval = await askCore({
question: "Plan includes deleting 100 files. Proceed?",
options: ["yes", "no", "show list first"],
timeout: 60000 // 1 min to respond
});
if (approval !== "yes") return { status: "aborted", reason: "user declined" };
}
// Continue with approved plan...
}
Impact: Without bidirectional channels, subagents must either be overly cautious (ask for everything upfront) or overly bold (proceed with assumptions).
4. Termination Conditions - Resource-Based Kills
Current state:
Timeout-based only: Subagent runs until task completes or timeout expires
No resource-based termination
Missing:
Memory limit kills (terminate if subagent exceeds RAM quota)
Cost threshold kills (terminate if API calls exceed budget)
Runaway output prevention (subagent generating gigabytes of logs)
v2 Design Consideration:
javascript
sessions_spawn({
task: "...",
limits: {
timeout: 600000, // 10 min max
maxMemory: 512, // MB
maxCost: 2.00, // USD
maxOutputSize: 10, // MB
maxToolCalls: 100, // Total tool invocations
stuckDetection: {
enabled: true,
sameToolRepeat: 5, // Flag if same tool called 5+ times consecutively
noProgressTimeout: 120000 // Flag if no output/tool calls for 2 min
}
},
onLimitExceeded: (limit, value) => {
logFailure({ subagent, limit, value });
return { action: 'terminate', notify: 'core' };
}
})
Impact: Without resource-based kills, subagents can waste budget, exhaust memory, or spin indefinitely.
5. Post-Mortem - Learning from Failures
Update (v2.1 → v2.2): A lightweight v0 of post-mortem logging is now implementable without framework changes. The crash report schema defined in templates/proxy-recovery.md gives you structured failure data per-spawn. Core reads crash reports and routes them. This covers the "what failed and why" dimension immediately.
What still requires framework work (see v2 roadmap below): automated outcome analytics, pattern detection across spawns, success rate tracking. But single-spawn forensics — you can ship that now.
Current state:
Success logging only: AGENTS.md records completed subagents
No failure tracking or pattern analysis
Partial exception: Security proxies using proxy-recovery.md pattern get crash reports per spawn
Missing:
Failure logging (why did subagent fail?)
Common failure patterns (which tasks/agents fail most?)
Cost vs value analysis (was the subagent worth the spend?)
Success rate tracking per agent type (CoderAgent: 85%, ResearchAgent: 92%, etc.)
Improvement loop (adjust spawn parameters based on historical outcomes)