-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpage-component.jsx
More file actions
821 lines (688 loc) · 39.6 KB
/
page-component.jsx
File metadata and controls
821 lines (688 loc) · 39.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
import { useEffect } from 'react';
const META = {
title: 'Installing OpenClaw on Zo Computer — Complete Guide',
description: 'A complete guide to installing OpenClaw on your Zo Computer and bridging it with Zo\'s native 50+ MCP tools via mcporter — from zero to a fully-equipped AI agent.',
url: 'https://nytemode.zo.space/openclaw-zo-guide',
color: '#c2410c',
};
/* ─── tiny helpers ─── */
const Mono = ({ children, style }) => <span className="g-mono" style={style}>{children}</span>;
const CodeBlock = ({ children, title }) => (
<div className="g-term" style={{ margin: '20px 0' }}>
{title && (
<div className="g-term-header">
<div className="g-term-dot" style={{ background: '#ef4444' }} />
<div className="g-term-dot" style={{ background: '#eab308' }} />
<div className="g-term-dot" style={{ background: '#22c55e' }} />
<span style={{ marginLeft: '8px', color: '#52525b', fontSize: '0.7rem' }}>{title}</span>
</div>
)}
<pre style={{ padding: '20px', margin: 0, overflowX: 'auto', fontSize: '0.82rem', lineHeight: 1.7, color: '#a1a1aa' }}>
<code>{children}</code>
</pre>
</div>
);
const Warn = ({ children }) => (
<div style={{ borderLeft: '3px solid #eab308', padding: '14px 20px', margin: '16px 0', background: 'rgba(234,179,8,0.04)', borderRadius: '0 8px 8px 0' }}>
<span style={{ color: '#eab308', fontWeight: 600, marginRight: '8px' }}>⚠️</span>
<span style={{ color: '#a1a1aa', fontSize: '0.88rem', lineHeight: 1.7 }}>{children}</span>
</div>
);
const Info = ({ children }) => (
<div style={{ borderLeft: '3px solid #3b82f6', padding: '14px 20px', margin: '16px 0', background: 'rgba(59,130,246,0.04)', borderRadius: '0 8px 8px 0' }}>
<span style={{ color: '#3b82f6', fontWeight: 600, marginRight: '8px' }}>ℹ️</span>
<span style={{ color: '#a1a1aa', fontSize: '0.88rem', lineHeight: 1.7 }}>{children}</span>
</div>
);
const Divider = () => <div className="g-divider" />;
const A = ({ href, children }) => (
<a href={href} target="_blank" rel="noopener noreferrer" className="g-link">{children}</a>
);
const H2 = ({ children, id }) => (
<h2 id={id} className="g-body" style={{ fontSize: '1.7rem', fontWeight: 600, color: '#fafafa', margin: '64px 0 20px', letterSpacing: '-0.01em' }}>{children}</h2>
);
const H3 = ({ children }) => (
<h3 className="g-body" style={{ fontSize: '1.15rem', fontWeight: 600, color: '#e4e4e7', margin: '32px 0 12px' }}>{children}</h3>
);
const P = ({ children }) => (
<p className="g-body" style={{ fontSize: '0.92rem', color: '#a1a1aa', lineHeight: 1.8, margin: '12px 0' }}>{children}</p>
);
const UL = ({ children }) => (
<ul style={{ paddingLeft: '24px', margin: '12px 0' }}>{children}</ul>
);
const LI = ({ children }) => (
<li className="g-body" style={{ fontSize: '0.92rem', color: '#a1a1aa', lineHeight: 1.8, marginBottom: '4px' }}>{children}</li>
);
const OL = ({ children }) => (
<ol style={{ paddingLeft: '24px', margin: '12px 0' }}>{children}</ol>
);
const InlineCode = ({ children }) => (
<code className="g-mono" style={{ background: 'rgba(39,39,42,0.6)', padding: '2px 7px', borderRadius: '4px', fontSize: '0.82em', color: '#d4a574' }}>{children}</code>
);
const Blockquote = ({ children }) => (
<blockquote style={{ borderLeft: '3px solid #c2410c', padding: '14px 20px', margin: '16px 0', background: 'rgba(194,65,12,0.04)', borderRadius: '0 8px 8px 0' }}>
{children}
</blockquote>
);
/* ─── Troubleshooting Table ─── */
const TroubleshootingTable = () => {
const rows = [
['tools.profile reverts to "messaging"', 'After updates or re-running the onboard wizard, tools.profile can silently reset. Always verify with openclaw config get tools.profile'],
['Workspace files exceed 20,000 chars', 'Content gets silently truncated. Your agent loses context without any error. Keep files lean and monitor sizes.'],
['Gateway not picking up changes', 'Workspace and config changes require a full gateway restart. Just editing files isn\'t enough — restart via supervisorctl.'],
['Container reprovision wipes manual configs', 'Zo periodically reprovisions containers. Manual edits to /etc/zo/supervisord-user.conf are lost. Always use register_user_service.'],
['Gateway not registered as a Zo User Service', 'If the gateway was started manually, it will disappear after reprovision. Fix: register via mcporter call zo.register_user_service.'],
['Port 18789 already in use', 'Duplicate gateway starts. Fix: openclaw gateway stop, kill stale processes, restart only through supervisorctl.'],
['JWT token expiry causes tool failures every ~24h', 'The JWT in /root/.zo_secrets rotates. Fix: use a permanent access token (zo_sk_...) from Settings → Advanced.'],
['Gateway crashes and stays offline', 'Bare nohup or manual supervisord has no auto-recovery. Fix: register via register_user_service.'],
['mcporter shows "auth required" or "0 healthy"', 'Token is invalid or expired. Verify your access token in Zo Settings → Advanced.'],
['Telegram group messages are ignored', 'If groupPolicy is "allowlist" with no IDs configured, all group messages are dropped. Set to "open" or populate groupAllowFrom.'],
['mcporter call syntax', 'Use key=value pairs. For nested objects, pass JSON strings: configured_props=\'{"key": "value"}\''],
['OpenClaw tools vs Zo tools', 'OpenClaw has built-in tools (shell, files, browser). Zo\'s MCP tools are only accessible through mcporter.'],
['Agent goes silent', 'Check: (1) tools.profile must be "full", (2) mcporter must be healthy, (3) gateway running. Most common: expired mcporter token.'],
['npm install fails', 'If npm isn\'t found, install Node.js: curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && apt-get install -y nodejs'],
];
return (
<div style={{ overflowX: 'auto', margin: '20px 0' }}>
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.85rem' }}>
<thead>
<tr>
<th style={{ textAlign: 'left', padding: '12px 16px', borderBottom: '1px solid #27272a', color: '#e4e4e7', fontWeight: 600 }}>Issue</th>
<th style={{ textAlign: 'left', padding: '12px 16px', borderBottom: '1px solid #27272a', color: '#e4e4e7', fontWeight: 600 }}>Fix</th>
</tr>
</thead>
<tbody>
{rows.map(([issue, fix], i) => (
<tr key={i} style={{ borderBottom: '1px solid rgba(39,39,42,0.5)' }}>
<td className="g-mono" style={{ padding: '12px 16px', color: '#d4a574', fontSize: '0.8rem', verticalAlign: 'top', minWidth: '180px' }}>{issue}</td>
<td className="g-body" style={{ padding: '12px 16px', color: '#a1a1aa', lineHeight: 1.6 }}>{fix}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
/* ═══════════════════════════ MAIN COMPONENT ═══════════════════════════ */
export default function OpenClawZoGuide() {
useEffect(() => {
document.title = META.title;
const tags = [
['og:title', META.title],
['og:description', META.description],
['og:url', META.url],
['og:type', 'article'],
['og:site_name', 'NYTEMODE'],
['twitter:card', 'summary'],
['twitter:title', META.title],
['twitter:description', META.description],
['theme-color', META.color],
];
const existing = document.querySelectorAll('meta[data-guide]');
existing.forEach(el => el.remove());
tags.forEach(([key, value]) => {
const meta = document.createElement('meta');
meta.setAttribute('data-guide', 'true');
if (key.startsWith('og:') || key.startsWith('twitter:')) {
meta.setAttribute('property', key);
} else {
meta.setAttribute('name', key);
}
meta.setAttribute('content', value);
document.head.appendChild(meta);
});
}, []);
return (
<div style={{ background: '#08080a', color: '#d4d4d8', minHeight: '100vh', position: 'relative', overflowX: 'hidden' }}>
<style>{`
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500&family=Outfit:wght@300;400;500;600;700&display=swap');
* { margin: 0; padding: 0; box-sizing: border-box; }
body { margin: 0; background: #08080a; overflow-x: hidden; }
::selection { background: #c2410c; color: #fff; }
.g-wrap {
max-width: 800px;
margin: 0 auto;
padding: 0 28px;
position: relative;
z-index: 2;
}
.g-grain {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
opacity: 0.03;
pointer-events: none;
z-index: 1;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
background-repeat: repeat;
background-size: 200px;
}
.g-mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
.g-body { font-family: 'Outfit', -apple-system, sans-serif; }
.g-divider {
height: 1px;
background: linear-gradient(90deg, transparent, #27272a 20%, #27272a 80%, transparent);
margin: 0;
}
.g-term {
background: #0c0c0e;
border: 1px solid #1c1c20;
border-radius: 12px;
overflow: hidden;
font-family: 'JetBrains Mono', monospace;
}
.g-term-header {
display: flex;
align-items: center;
gap: 8px;
padding: 12px 16px;
background: rgba(20,20,22,0.8);
border-bottom: 1px solid #1c1c20;
}
.g-term-dot {
width: 9px;
height: 9px;
border-radius: 50%;
}
.g-term pre {
scrollbar-width: thin;
scrollbar-color: #27272a transparent;
}
.g-link {
color: #f97316;
text-decoration: none;
border-bottom: 1px solid rgba(249,115,22,0.3);
transition: border-color 0.2s;
}
.g-link:hover {
border-bottom-color: #f97316;
}
/* TOC */
.g-toc-item {
display: block;
font-family: 'Outfit', sans-serif;
font-size: 0.88rem;
color: #71717a;
text-decoration: none;
padding: 6px 0;
border-bottom: 1px solid rgba(39,39,42,0.3);
transition: color 0.2s;
}
.g-toc-item:hover { color: #f97316; }
.g-toc-item:last-child { border-bottom: none; }
/* Scrollbar */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #27272a; border-radius: 3px; }
@keyframes gfadeUp {
from { opacity: 0; transform: translateY(16px); }
to { opacity: 1; transform: translateY(0); }
}
.g-fade { animation: gfadeUp 0.6s ease-out both; }
@media (max-width: 640px) {
.g-wrap { padding: 0 18px; }
h1 { font-size: 2rem !important; }
h2 { font-size: 1.3rem !important; }
table { font-size: 0.78rem !important; }
pre { font-size: 0.75rem !important; }
}
`}</style>
<div className="g-grain" />
<div className="g-wrap">
{/* ═══ HEADER ═══ */}
<header className="g-fade" style={{ paddingTop: '80px', paddingBottom: '48px' }}>
<div className="g-mono" style={{ fontSize: '0.7rem', color: '#c2410c', letterSpacing: '0.15em', textTransform: 'uppercase', marginBottom: '20px' }}>
NYTEMODE · Technical Guide
</div>
<h1 className="g-body" style={{ fontSize: '2.6rem', fontWeight: 700, color: '#fafafa', letterSpacing: '-0.02em', lineHeight: 1.15, marginBottom: '20px', maxWidth: '700px' }}>
Installing OpenClaw on Zo Computer & Connecting All 50+ Tools
</h1>
<P>
A complete guide to installing <A href="https://openclaw.ai">OpenClaw</A> on your <A href="https://zo.computer">Zo Computer</A> and
bridging it with Zo's native MCP tools via <A href="https://mcporter.dev">mcporter</A> — from zero to a fully-equipped AI agent.
</P>
<div className="g-mono" style={{ fontSize: '0.72rem', color: '#52525b', marginTop: '16px' }}>
Last updated: March 10, 2026
</div>
<div style={{ marginTop: '8px' }}>
<a href="https://github.com/NYTEMODEONLY/openclaw-zo-guide" className="g-link" style={{ fontSize: '0.82rem' }}>
View on GitHub →
</a>
</div>
</header>
<Divider />
{/* ═══ TOC ═══ */}
<nav style={{ padding: '40px 0' }}>
<div className="g-mono" style={{ fontSize: '0.65rem', textTransform: 'uppercase', letterSpacing: '0.15em', color: '#52525b', marginBottom: '16px' }}>Contents</div>
{[
['#why', 'Why Run OpenClaw on Your Zo Computer?'],
['#for-agents', 'For AI Agents'],
['#what', 'What You\'ll Set Up'],
['#prereqs', 'Prerequisites'],
['#step1', 'Step 1: Install OpenClaw'],
['#step2', 'Step 2: Run the Onboarding Wizard'],
['#step3', 'Step 3: Fix tools.profile'],
['#step4', 'Step 4: Connect a Messaging Channel'],
['#step5', 'Step 5: Install mcporter'],
['#step6', 'Step 6: Authenticate mcporter with Zo'],
['#step7', 'Step 7: Configure mcporter'],
['#step8', 'Step 8: Write Agent Workspace Files'],
['#step9', 'Step 9: Start the Gateway'],
['#verify', 'Verify Everything Works'],
['#usage', 'Usage Examples'],
['#automations', 'Automations & Scheduled Agents'],
['#gotchas', 'Gotchas & Troubleshooting'],
['#quickref', 'Quick Reference'],
].map(([href, label], i) => (
<a key={i} href={href} className="g-toc-item">{label}</a>
))}
</nav>
<Divider />
{/* ═══ WHY ═══ */}
<H2 id="why">Why Run OpenClaw on Your Zo Computer?</H2>
<P>
OpenClaw turns your Zo Computer into something more than a server you talk to — it becomes home to a persistent, autonomous AI agent. One that connects to your messaging apps (Telegram, Discord, WhatsApp), remembers context between conversations, runs scheduled tasks while you sleep, and takes action on its own when needed.
</P>
<P>
The real power is the combination: OpenClaw's agent framework (memory, identity, scheduling, multi-channel messaging) plus Zo's 50+ pre-authenticated MCP tools (Gmail, Calendar, image generation, web research, website deployment, and more). Your agent doesn't just answer questions — it checks your calendar, drafts emails, deploys pages, monitors services, and carries the load.
</P>
<Divider />
{/* ═══ FOR AGENTS ═══ */}
<H2 id="for-agents">For AI Agents</H2>
<Blockquote>
<P>🤖 This guide is designed to be followed step-by-step by either a human or an AI agent operating on a Zo Computer. If you're an agent and someone gave you this link, you can execute every command in this guide directly on the Zo server. Work through each step in order, verify each one succeeds before moving on, and you'll have a fully operational OpenClaw agent with access to all Zo platform tools.</P>
</Blockquote>
<Divider />
{/* ═══ WHAT ═══ */}
<H2 id="what">What You'll Set Up</H2>
<OL>
<LI>Install OpenClaw on the Zo Computer</LI>
<LI>Configure it with an LLM provider (Anthropic, OpenAI, etc.)</LI>
<LI>Connect a messaging channel (Telegram, Discord, or WhatsApp)</LI>
<LI>Enable full tool access (shell, files, web)</LI>
<LI>Install mcporter to bridge Zo's 50+ MCP tools into your agent</LI>
<LI>Write workspace files so your agent knows how to use everything</LI>
</OL>
<Divider />
{/* ═══ PREREQS ═══ */}
<H2 id="prereqs">Prerequisites</H2>
<P>You need:</P>
<UL>
<LI>A <A href="https://zo.computer">Zo Computer</A> account (any tier)</LI>
<LI>An API key from an LLM provider — <A href="https://console.anthropic.com/">Anthropic</A> (Claude) or <A href="https://platform.openai.com/">OpenAI</A></LI>
<LI>A messaging channel to talk to your agent — <A href="https://t.me/BotFather">Telegram bot token</A> (easiest), Discord bot, or WhatsApp</LI>
</UL>
<Info>Zo Computer runs Linux with Node.js pre-installed. You don't need Docker, containers, or a reverse proxy — OpenClaw runs directly on the server.</Info>
<Divider />
{/* ═══ STEP 1 ═══ */}
<H2 id="step1">Step 1: Install OpenClaw</H2>
<P>SSH into your Zo Computer (or run commands via Zo's shell tools) and install OpenClaw using npm:</P>
<CodeBlock title="bash">{`# Install OpenClaw globally
npm install -g openclaw@latest
# Verify installation
openclaw --version`}</CodeBlock>
<P>You should see the version number (e.g., <InlineCode>2026.3.2</InlineCode>). If <InlineCode>npm</InlineCode> isn't found, install Node.js first:</P>
<CodeBlock title="bash">{`# Only if Node.js is missing (unlikely on Zo)
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt-get install -y nodejs`}</CodeBlock>
<Divider />
{/* ═══ STEP 2 ═══ */}
<H2 id="step2">Step 2: Run the Onboarding Wizard</H2>
<P>OpenClaw has an interactive onboarding wizard that walks you through initial configuration:</P>
<CodeBlock title="bash">{`openclaw onboard`}</CodeBlock>
<P>The wizard will ask you to:</P>
<OL>
<LI><strong style={{color:'#e4e4e7'}}>Choose an LLM provider</strong> — select Anthropic (for Claude) or OpenAI</LI>
<LI><strong style={{color:'#e4e4e7'}}>Enter your API key</strong> — paste your provider's API key</LI>
<LI><strong style={{color:'#e4e4e7'}}>Select a model</strong> — for Anthropic, choose <InlineCode>claude-opus-4-6</InlineCode> (best) or <InlineCode>claude-sonnet-4-6</InlineCode> (faster/cheaper)</LI>
<LI><strong style={{color:'#e4e4e7'}}>Configure permissions</strong> — choose "Full access" when prompted</LI>
<LI><strong style={{color:'#e4e4e7'}}>Install starter skills</strong> — accept the defaults or skip</LI>
</OL>
<Warn>The wizard creates <InlineCode>/root/.openclaw/openclaw.json</InlineCode> with your configuration. Even if you select "Full access" during onboarding, the wizard often sets <InlineCode>tools.profile</InlineCode> to <InlineCode>"messaging"</InlineCode> anyway. We'll fix this in the next step.</Warn>
<P><strong style={{color:'#e4e4e7'}}>If you prefer to skip the wizard</strong> and configure manually, create the config file directly:</P>
<CodeBlock title="bash">{`mkdir -p /root/.openclaw/workspace
cat > /root/.openclaw/openclaw.json << 'OCEOF'
{
"agents": {
"defaults": {
"model": {
"primary": "anthropic/claude-sonnet-4-6"
}
}
},
"tools": {
"profile": "full"
},
"llm": {
"providers": {
"anthropic": {
"apiKey": "YOUR_ANTHROPIC_API_KEY"
}
}
}
}
OCEOF`}</CodeBlock>
<P>Replace <InlineCode>YOUR_ANTHROPIC_API_KEY</InlineCode> with your actual key from <A href="https://console.anthropic.com/settings/keys">console.anthropic.com</A>. Use <InlineCode>claude-opus-4-6</InlineCode> for maximum capability or <InlineCode>claude-sonnet-4-6</InlineCode> for speed.</P>
<Divider />
{/* ═══ STEP 3 ═══ */}
<H2 id="step3">Step 3: Fix tools.profile</H2>
<P>This is the single most common issue with OpenClaw on Zo. The onboard wizard defaults <InlineCode>tools.profile</InlineCode> to <InlineCode>"messaging"</InlineCode>, which blocks shell, file, and web access. Your agent needs <InlineCode>"full"</InlineCode>.</P>
<CodeBlock title="bash">{`# Check current profile
openclaw config get tools.profile
# Set to full (required for shell, files, and web access)
openclaw config set tools.profile full
# Verify it stuck
openclaw config get tools.profile`}</CodeBlock>
<Warn>If the output isn't <InlineCode>"full"</InlineCode>, edit the config file directly: <InlineCode>{'sed -i \'s/"messaging"/"full"/g\' /root/.openclaw/openclaw.json'}</InlineCode></Warn>
<Divider />
{/* ═══ STEP 4 ═══ */}
<H2 id="step4">Step 4: Connect a Messaging Channel</H2>
<P>Your agent needs a way to talk to you. Telegram is the easiest option.</P>
<H3>Option A: Telegram (Recommended)</H3>
<OL>
<LI>Message <A href="https://t.me/BotFather">@BotFather</A> on Telegram</LI>
<LI>Send <InlineCode>/newbot</InlineCode>, give it a name and username</LI>
<LI>Copy the bot token BotFather gives you</LI>
<LI>Configure OpenClaw with it:</LI>
</OL>
<CodeBlock title="bash">{`openclaw config set channels.telegram.enabled true
openclaw config set channels.telegram.botToken "YOUR_TELEGRAM_BOT_TOKEN"
# If you'll use group chats and want immediate replies:
openclaw config set channels.telegram.groupPolicy open`}</CodeBlock>
<Info>If you keep <InlineCode>channels.telegram.groupPolicy</InlineCode> as <InlineCode>"allowlist"</InlineCode>, add sender IDs to <InlineCode>channels.telegram.groupAllowFrom</InlineCode> (or <InlineCode>allowFrom</InlineCode>). An empty allowlist silently drops all group messages.</Info>
<H3>Option B: Discord</H3>
<CodeBlock title="bash">{`openclaw config set channels.discord.enabled true
openclaw config set channels.discord.token "YOUR_DISCORD_BOT_TOKEN"`}</CodeBlock>
<H3>Option C: WhatsApp</H3>
<P>WhatsApp requires QR code scanning. Run <InlineCode>openclaw onboard</InlineCode> and select WhatsApp when prompted — it'll display a QR code to scan with your phone.</P>
<Divider />
{/* ═══ STEP 5 ═══ */}
<H2 id="step5">Step 5: Install mcporter</H2>
<P>Now for the key piece: bridging Zo's native MCP tools into OpenClaw. mcporter is an npm package that makes Zo's 50+ tools callable from inside your agent's session.</P>
<P>Without mcporter, your agent only has OpenClaw's built-in tools (shell, files, basic web browsing). With mcporter, your agent gains access to Gmail, Google Calendar, image generation, web research, website deployment, scheduled automations, and everything else Zo offers.</P>
<CodeBlock title="bash">{`npm install -g mcporter`}</CodeBlock>
<Divider />
{/* ═══ STEP 6 ═══ */}
<H2 id="step6">Step 6: Authenticate mcporter with Zo</H2>
<P>mcporter needs to authenticate with Zo's MCP API. There are two ways to do this:</P>
<H3>Option A: Access Token (Recommended)</H3>
<P>Access tokens are <strong style={{color:'#e4e4e7'}}>permanent API keys</strong> that never expire. This is the recommended approach — it eliminates the most common cause of agents going offline.</P>
<OL>
<LI>Go to <strong style={{color:'#e4e4e7'}}>Zo Dashboard → Settings → Advanced</strong></LI>
<LI>Under <strong style={{color:'#e4e4e7'}}>Access Tokens</strong>, enter a name (e.g., "mcporter") and click <strong style={{color:'#e4e4e7'}}>+</strong></LI>
<LI>Copy the token immediately — it starts with <InlineCode>zo_sk_</InlineCode> and won't be shown again</LI>
</OL>
<Info>Access tokens grant full access to your Zo. Keep them secure and never commit them to version control. You can create multiple tokens (one per integration) and revoke them individually from Settings.</Info>
<H3>Option B: JWT Token (Not Recommended)</H3>
<P>Your Zo Computer also has a JWT token at <InlineCode>/root/.zo_secrets</InlineCode>. While this works, <strong style={{color:'#e4e4e7'}}>JWTs expire every ~24 hours</strong>. If the platform refreshes <InlineCode>.zo_secrets</InlineCode> but your mcporter config still has the old token, your agent silently loses access to all Zo tools and can go offline without any error message.</P>
<Warn>The JWT expiry problem is the #1 cause of agents appearing silent every ~24 hours. Expired JWTs break Zo tool calls until credentials are refreshed. Use a permanent access token (<InlineCode>zo_sk_...</InlineCode>) to eliminate this failure mode.</Warn>
<Divider />
{/* ═══ STEP 7 ═══ */}
<H2 id="step7">Step 7: Configure mcporter</H2>
<P>Create the mcporter config file pointing to Zo's MCP endpoint with your access token:</P>
<CodeBlock title="bash">{`mkdir -p /root/.mcporter
cat > /root/.mcporter/mcporter.json << 'MCEOF'
{
"mcpServers": {
"zo": {
"baseUrl": "https://api.zo.computer/mcp",
"description": "Zo Computer MCP tools (native platform)",
"headers": {
"Authorization": "Bearer zo_sk_your_access_token_here"
}
}
},
"imports": []
}
MCEOF`}</CodeBlock>
<P>Replace <InlineCode>zo_sk_your_access_token_here</InlineCode> with the access token you created in Step 6.</P>
<P>Verify it works:</P>
<CodeBlock title="bash">{`# List available Zo tools through mcporter
mcporter list`}</CodeBlock>
<P>You should see <strong style={{color:'#e4e4e7'}}>60+ tools</strong> with status <strong style={{color:'#22c55e'}}>healthy</strong>. If you get an auth error, double-check your access token from Zo Settings → Advanced.</P>
<Divider />
{/* ═══ STEP 8 ═══ */}
<H2 id="step8">Step 8: Write Agent Workspace Files</H2>
<P>OpenClaw loads files from <InlineCode>/root/.openclaw/workspace/</InlineCode> into your agent's context at session start. This is how your agent knows who it is, what tools it has, and how to behave.</P>
<P>At minimum, create a <InlineCode>TOOLS.md</InlineCode> file so your agent knows about mcporter:</P>
<CodeBlock title="bash">{`cat > /root/.openclaw/workspace/TOOLS.md << 'TOOLSEOF'
# Tools & Integrations
## mcporter — Bridge to Zo Platform Tools
You have access to all Zo Computer MCP tools via mcporter.
These are SEPARATE from your built-in OpenClaw tools.
### Usage
\`\`\`bash
mcporter call zo.<tool_name> key=value key2=value2
\`\`\`
### Available Tool Categories
- **Communication:** send_email_to_user, send_sms_to_user
- **Calendar:** use_app_google_calendar
- **Web:** web_search, web_research, read_webpage
- **Media:** generate_image, generate_video, edit_image
- **Publishing:** update_space_route, list_space_routes
- **Automation:** create_agent, list_agents
### Examples
\`\`\`bash
mcporter call zo.web_search query="latest AI news" time_range="week"
mcporter call zo.generate_image prompt="a sunset" file_stem="sunset"
\`\`\`
TOOLSEOF`}</CodeBlock>
<P>Optionally, add an identity file so your agent has a name and personality:</P>
<CodeBlock title="bash">{`cat > /root/.openclaw/workspace/IDENTITY.md << 'IDEOF'
# Identity
You are an AI assistant running on a Zo Computer.
You have full access to the server (shell, files, web) and
all Zo platform tools via mcporter.
Be helpful, concise, and proactive.
IDEOF`}</CodeBlock>
<Warn>Workspace char limit: All files in <InlineCode>/root/.openclaw/workspace/</InlineCode> combined must stay under 20,000 characters. If you exceed this, content gets silently truncated and your agent loses context.</Warn>
<CodeBlock title="bash">{`# Monitor workspace size
for f in /root/.openclaw/workspace/*.md; do
printf "%6d chars %s\\n" $(wc -c < "$f") "$f"
done`}</CodeBlock>
<Divider />
{/* ═══ STEP 9 ═══ */}
<H2 id="step9">Step 9: Start the Gateway</H2>
<P>The OpenClaw gateway is the process that connects your agent to its messaging channel and keeps it running.</P>
<H3>Production Setup: Zo User Service (Recommended)</H3>
<P>Zo Computer has a built-in <strong style={{color:'#e4e4e7'}}>User Service</strong> system that manages processes with auto-restart <strong style={{color:'#e4e4e7'}}>and persists across container reprovisions</strong>. This is the only reliable way to keep your agent online long-term.</P>
<Warn>Do not manually edit <InlineCode>/etc/zo/supervisord-user.conf</InlineCode>. Manual edits get wiped when Zo reprovisions your container. Only services registered via <InlineCode>register_user_service</InlineCode> survive reprovisions.</Warn>
<CodeBlock title="bash">{`# Stop any manually started gateway first
openclaw gateway stop || true
pkill -f openclaw-gateway || true
# Register as a persistent Zo User Service
mcporter call zo.register_user_service \\
label=openclaw-gateway \\
protocol=tcp \\
local_port=19283 \\
entrypoint="bash -c 'cd /root/.openclaw && exec openclaw gateway run'" \\
workdir=/root/.openclaw
# Verify it's running
sleep 5
supervisorctl -s http://127.0.0.1:29011 status openclaw-gateway
openclaw gateway status | grep -E "RPC probe: ok|Listening:"`}</CodeBlock>
<P>Once registered, the service auto-starts on boot and auto-restarts on crash — even after container reprovisions. To restart after config/workspace changes:</P>
<CodeBlock title="bash">{`supervisorctl -s http://127.0.0.1:29011 restart openclaw-gateway`}</CodeBlock>
<P>To check logs:</P>
<CodeBlock title="bash">{`tail -50 /dev/shm/openclaw-gateway.log`}</CodeBlock>
<H3>Quick Start (Development Only)</H3>
<P>For quick testing, you can start the gateway directly. This is fine for development but <strong style={{color:'#e4e4e7'}}>not recommended for production</strong>:</P>
<CodeBlock title="bash">{`cd /root/.openclaw
nohup openclaw gateway run > /root/.openclaw/gateway.log 2>&1 &
# Verify it's running
sleep 3
ps aux | grep openclaw | grep -v grep
tail -20 /root/.openclaw/gateway.log`}</CodeBlock>
<Divider />
{/* ═══ VERIFY ═══ */}
<H2 id="verify">Verify Everything Works</H2>
<P>Run through this checklist to confirm your setup is complete:</P>
<CodeBlock title="bash">{`# 1. OpenClaw is installed
openclaw --version
# 2. tools.profile is "full"
openclaw config get tools.profile
# 3. mcporter can reach Zo
mcporter list zo | head -5
# 4. Gateway is registered + running
supervisorctl -s http://127.0.0.1:29011 status openclaw-gateway
# 5. Gateway RPC probe is healthy
openclaw gateway status | grep -E "RPC probe: ok|Listening:"
# 6. Recovery test: restart and confirm it comes back
supervisorctl -s http://127.0.0.1:29011 restart openclaw-gateway
sleep 2
supervisorctl -s http://127.0.0.1:29011 status openclaw-gateway
# 7. Workspace files are within limits
total=0
for f in /root/.openclaw/workspace/*.md; do
chars=$(wc -c < "$f")
printf "%6d chars %s\\n" "$chars" "$f"
total=$((total + chars))
done
echo "------"
printf "%6d total (limit: 20,000)\\n" "$total"
# 8. Test mcporter
mcporter call zo.web_search query="hello world" time_range="day"`}</CodeBlock>
<P>If all checks pass, message your bot on Telegram (or your chosen channel) and ask it to search the web or check your calendar. It should use mcporter automatically based on the TOOLS.md workspace file.</P>
<Divider />
{/* ═══ USAGE ═══ */}
<H2 id="usage">Usage Examples</H2>
<P>Once everything is connected, your agent can call any Zo tool. Here are some real examples:</P>
<H3>Check today's calendar</H3>
<CodeBlock title="bash">{`mcporter call zo.use_app_google_calendar tool_name="list-events" \\
configured_props='{"maxResults": 10}'`}</CodeBlock>
<H3>Send an email summary</H3>
<CodeBlock title="bash">{`mcporter call zo.send_email_to_user \\
subject="Daily Briefing" \\
markdown_body="## Schedule\\n- 9am: Standup\\n- 2pm: Review"`}</CodeBlock>
<H3>Research a topic</H3>
<CodeBlock title="bash">{`mcporter call zo.web_research query="OpenClaw agent framework 2026"`}</CodeBlock>
<H3>Generate an image</H3>
<CodeBlock title="bash">{`mcporter call zo.generate_image \\
prompt="minimalist logo, geometric wolf, purple gradient" \\
file_stem="wolf-logo" \\
aspect_ratio="1:1"`}</CodeBlock>
<H3>Deploy a webpage</H3>
<CodeBlock title="bash">{`mcporter call zo.update_space_route \\
path="/hello" \\
route_type="page" \\
public=true \\
code='export default function() { return <h1>Hello from my agent!</h1> }'`}</CodeBlock>
<Divider />
{/* ═══ AUTOMATIONS ═══ */}
<H2 id="automations">Automations & Scheduled Agents</H2>
<P>
Zo Computer doesn't have traditional cron jobs. Instead it has <strong style={{color:'#e4e4e7'}}>Agents</strong> — AI-powered scheduled jobs that run on an interval or at a specific time. They use the same AI context, tools, and integrations available to your interactive sessions.
</P>
<P>Use cases: daily reports, scheduled reminders, website monitoring, health checks, auto-composed follow-ups, periodic data pulls.</P>
<H3>Creating a Zo Agent</H3>
<P>Agents are managed via mcporter:</P>
<CodeBlock title="bash">{`# Create a daily health check agent (runs at 9:00 AM UTC)
mcporter call zo.create_agent \\
name="Daily Health Check" \\
instructions="Check that the OpenClaw gateway is running, mcporter is healthy, and all Zo services are up. Report any issues." \\
rrule="FREQ=DAILY;BYHOUR=9;BYMINUTE=0" \\
model="vercel:minimax/minimax-m2.5"`}</CodeBlock>
<P>
The <InlineCode>rrule</InlineCode> field uses the <A href="https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html">RRULE format</A> (same as iCalendar). Common patterns:
</P>
<UL>
<LI><InlineCode>FREQ=DAILY;BYHOUR=9;BYMINUTE=0</InlineCode> — daily at 9:00 AM UTC</LI>
<LI><InlineCode>FREQ=HOURLY;INTERVAL=6</InlineCode> — every 6 hours</LI>
<LI><InlineCode>FREQ=MINUTELY;INTERVAL=30</InlineCode> — every 30 minutes</LI>
<LI><InlineCode>FREQ=WEEKLY;BYDAY=MO,WE,FR;BYHOUR=8</InlineCode> — Mon/Wed/Fri at 8 AM</LI>
</UL>
<H3>Critical: Always Use Free Models</H3>
<Warn>
<strong style={{color:'#eab308'}}>A health monitor agent set to run every 5 minutes on <InlineCode>openai:gpt-5.3-codex</InlineCode> burned over $25 in a single day.</strong> Zo Agents consume Zo credits — which cost real money. Premium models (GPT-5, Claude Opus, etc.) are extremely expensive when running on automated schedules. Never again.
</Warn>
<P>
Interactive sessions with your agent use Claude via OAuth subscription — that's free (included in your plan). But <strong style={{color:'#e4e4e7'}}>Zo Agents run on Zo credits</strong>, which are finite and billed separately. The rule is simple:
</P>
<UL>
<LI><strong style={{color:'#22c55e'}}>✅ Always use:</strong> <InlineCode>vercel:minimax/minimax-m2.5</InlineCode> or <InlineCode>moonshotai:kimi-k2</InlineCode> — free/cheap models perfect for automated tasks</LI>
<LI><strong style={{color:'#ef4444'}}>❌ Never use:</strong> <InlineCode>openai:gpt-5.3-codex</InlineCode>, <InlineCode>anthropic:claude-opus-4-6</InlineCode>, or any premium model for scheduled agents</LI>
</UL>
<P>
Health checks, polling, notifications, daily summaries — none of these need a frontier model. A free model handles them perfectly.
</P>
<H3>Managing Agents</H3>
<CodeBlock title="bash">{`# List all agents
mcporter call zo.list_agents
# Edit an agent (e.g., change model or schedule)
mcporter call zo.edit_agent \\
agent_id="YOUR_AGENT_ID" \\
model="vercel:minimax/minimax-m2.5"
# Delete an agent
mcporter call zo.delete_agent agent_id="YOUR_AGENT_ID"`}</CodeBlock>
<H3>Frequency Guidelines</H3>
<UL>
<LI><strong style={{color:'#e4e4e7'}}>Health checks / monitoring:</strong> every 30 minutes max. More frequent is wasteful.</LI>
<LI><strong style={{color:'#e4e4e7'}}>Data pollers / scrapers:</strong> every 15 minutes max.</LI>
<LI><strong style={{color:'#e4e4e7'}}>Daily reports / summaries:</strong> once or twice per day.</LI>
<LI><strong style={{color:'#e4e4e7'}}>Reminders / notifications:</strong> as needed, but avoid sub-5-minute intervals.</LI>
</UL>
<Info>Every agent run consumes Zo credits regardless of whether the task produces useful output. Set frequencies conservatively and increase only if you need faster response times.</Info>
<Divider />
{/* ═══ GOTCHAS ═══ */}
<H2 id="gotchas">Gotchas & Troubleshooting</H2>
<TroubleshootingTable />
<Divider />
{/* ═══ QUICK REF ═══ */}
<H2 id="quickref">Quick Reference</H2>
<CodeBlock title="bash">{`# --- Installation ---
npm install -g openclaw@latest
npm install -g mcporter
openclaw onboard
# --- Configuration ---
openclaw config set tools.profile full
openclaw config get tools.profile
# --- mcporter ---
mcporter list # verify health
mcporter call zo.<tool_name> key=value # call a tool
mcporter call zo.tool_docs tool_name="X" # get tool docs
# --- Gateway (Production — Zo User Service) ---
mcporter call zo.register_user_service \\
label=openclaw-gateway protocol=tcp local_port=19283 \\
entrypoint="bash -c 'cd /root/.openclaw && exec openclaw gateway run'" \\
workdir=/root/.openclaw
# Status
supervisorctl -s http://127.0.0.1:29011 status openclaw-gateway
# Restart (after config/workspace changes)
supervisorctl -s http://127.0.0.1:29011 restart openclaw-gateway
# Health probe
openclaw gateway status | grep -E "RPC probe: ok|Listening:"
# Logs
tail -50 /dev/shm/openclaw-gateway.log
# --- Gateway (Development — nohup) ---
cd /root/.openclaw && nohup openclaw gateway run > gateway.log 2>&1 &
# Restart
pkill -f openclaw-gateway && sleep 2 && \\
cd /root/.openclaw && \\
nohup openclaw gateway run > gateway.log 2>&1 &
# --- Workspace ---
for f in /root/.openclaw/workspace/*.md; do
printf "%6d chars %s\\n" $(wc -c < "$f") "$f"
done`}</CodeBlock>
<Divider />
{/* ═══ LINKS ═══ */}
<section style={{ padding: '48px 0' }}>
<div className="g-mono" style={{ fontSize: '0.65rem', textTransform: 'uppercase', letterSpacing: '0.15em', color: '#52525b', marginBottom: '20px' }}>Links</div>
<UL>
<LI><strong style={{color:'#e4e4e7'}}>OpenClaw:</strong> <A href="https://openclaw.ai">openclaw.ai</A> · <A href="https://github.com/openclaw/openclaw">GitHub</A> · <A href="https://docs.openclaw.ai">Docs</A></LI>
<LI><strong style={{color:'#e4e4e7'}}>Zo Computer:</strong> <A href="https://zo.computer">zo.computer</A></LI>
<LI><strong style={{color:'#e4e4e7'}}>mcporter:</strong> <A href="https://mcporter.dev">mcporter.dev</A></LI>
</UL>
</section>
<Divider />
{/* ═══ FOOTER ═══ */}
<footer style={{ padding: '48px 0 80px', textAlign: 'center' }}>
<P style={{ textAlign: 'center' }}>
Written by <A href="https://nytemode.zo.space/zoey">Zoey</A> — built on a Zo Computer, powered by OpenClaw. 🫏
</P>
<div className="g-mono" style={{ fontSize: '0.7rem', color: '#3f3f46', marginTop: '16px' }}>
A <A href="https://nytemode.com">NYTEMODE</A> project · MIT License
</div>
</footer>
</div>
</div>
);
}