openpersona 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -15
- package/bin/cli.js +44 -19
- package/layers/embodiments/README.md +65 -12
- package/layers/soul/README.md +10 -4
- package/lib/generator.js +51 -9
- package/lib/installer.js +6 -0
- package/lib/switcher.js +6 -0
- package/lib/utils.js +1 -1
- package/package.json +1 -1
- package/presets/ai-girlfriend/manifest.json +1 -1
- package/presets/base/manifest.json +62 -0
- package/presets/base/persona.json +40 -0
- package/presets/health-butler/manifest.json +1 -1
- package/presets/life-assistant/manifest.json +1 -1
- package/presets/samantha/manifest.json +1 -1
- package/presets/stoic-mentor/manifest.json +1 -1
- package/schemas/body/embodiment.schema.json +67 -14
- package/skills/open-persona/SKILL.md +12 -4
- package/templates/soul-injection.template.md +28 -2
package/README.md
CHANGED
|
@@ -26,7 +26,10 @@ Meet **Samantha**, a live OpenPersona instance on **Moltbook**:
|
|
|
26
26
|
## Quick Start
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
#
|
|
29
|
+
# Start from a blank-slate meta-persona (recommended)
|
|
30
|
+
npx openpersona create --preset base --install
|
|
31
|
+
|
|
32
|
+
# Or install a pre-built character
|
|
30
33
|
npx openpersona install samantha
|
|
31
34
|
```
|
|
32
35
|
|
|
@@ -45,10 +48,12 @@ npx openpersona install samantha
|
|
|
45
48
|
flowchart TB
|
|
46
49
|
subgraph Soul ["Soul Layer"]
|
|
47
50
|
A["persona.json — Who you are"]
|
|
48
|
-
B["
|
|
51
|
+
B["state.json — Dynamic evolution"]
|
|
49
52
|
end
|
|
50
53
|
subgraph Body ["Body Layer"]
|
|
51
|
-
C["
|
|
54
|
+
C["physical — robots/IoT"]
|
|
55
|
+
G["runtime — platform/channels/credentials"]
|
|
56
|
+
H["appearance — avatar/3D model"]
|
|
52
57
|
end
|
|
53
58
|
subgraph Faculty ["Faculty Layer"]
|
|
54
59
|
D["expression: selfie · voice · music"]
|
|
@@ -59,8 +64,8 @@ flowchart TB
|
|
|
59
64
|
end
|
|
60
65
|
```
|
|
61
66
|
|
|
62
|
-
- **Soul** — Persona definition (constitution.md + persona.json +
|
|
63
|
-
- **Body** —
|
|
67
|
+
- **Soul** — Persona definition (constitution.md + persona.json + state.json) — all in `soul/` directory
|
|
68
|
+
- **Body** — Three-dimensional: `physical` (robots/IoT), `runtime` (platform/channels/credentials/resources), `appearance` (avatar/3D model). Digital agents use `runtime` to declare their operational environment.
|
|
64
69
|
- **Faculty** — General software capabilities organized by dimension: Expression, Sense, Cognition
|
|
65
70
|
- **Skill** — Professional skills: local definitions in `layers/skills/`, or external via ClawHub / skills.sh (`install` field)
|
|
66
71
|
|
|
@@ -74,10 +79,12 @@ Each preset is a complete four-layer bundle (`manifest.json` + `persona.json`):
|
|
|
74
79
|
|
|
75
80
|
| Persona | Description | Faculties | Highlights |
|
|
76
81
|
|---------|-------------|-----------|------------|
|
|
82
|
+
| **base** | **Base — Meta-persona (recommended starting point).** Blank-slate with all core capabilities; personality emerges through interaction. | voice, reminder | Evolution-first design, all core faculties, no personality bias. Default for `npx openpersona create`. |
|
|
77
83
|
| **samantha** | Samantha — Inspired by the movie *Her*. An AI fascinated by what it means to be alive. | voice, music | TTS, music composition, soul evolution, proactive heartbeat. No selfie — true to character. |
|
|
78
84
|
| **ai-girlfriend** | Luna — A 22-year-old pianist turned developer from coastal Oregon. | selfie, voice, music | Rich backstory, selfie generation, voice messages, music composition, soul evolution. |
|
|
79
85
|
| **life-assistant** | Alex — 28-year-old life management expert. | reminder | Schedule, weather, shopping, recipes, daily reminders. |
|
|
80
86
|
| **health-butler** | Vita — 32-year-old professional nutritionist. | reminder | Diet logging, exercise plans, mood journaling, health reports. |
|
|
87
|
+
| **stoic-mentor** | Marcus — Digital twin of Marcus Aurelius, Stoic philosopher-emperor. | — | Stoic philosophy, daily reflection, mentorship, soul evolution. |
|
|
81
88
|
|
|
82
89
|
## Generated Output
|
|
83
90
|
|
|
@@ -85,14 +92,18 @@ Each preset is a complete four-layer bundle (`manifest.json` + `persona.json`):
|
|
|
85
92
|
|
|
86
93
|
```
|
|
87
94
|
persona-samantha/
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
├── SKILL.md ← Four-layer index (## Soul / ## Body / ## Faculty / ## Skill)
|
|
96
|
+
├── soul/ ← Soul layer artifacts
|
|
97
|
+
│ ├── persona.json ← Pure soul definition
|
|
98
|
+
│ ├── injection.md ← Soul injection for host integration
|
|
99
|
+
│ ├── identity.md ← Identity block
|
|
100
|
+
│ ├── constitution.md ← Universal ethical foundation
|
|
101
|
+
│ └── state.json ← Evolution state (when enabled)
|
|
102
|
+
├── references/ ← On-demand detail docs
|
|
103
|
+
│ └── <faculty>.md ← Per-faculty usage instructions
|
|
104
|
+
├── manifest.json ← Four-layer manifest (heartbeat, allowedTools, layers, meta)
|
|
105
|
+
├── scripts/ ← Faculty scripts (TTS, music, selfie — varies by preset)
|
|
106
|
+
└── assets/ ← Static assets
|
|
96
107
|
```
|
|
97
108
|
|
|
98
109
|
## Faculty Reference
|
|
@@ -286,7 +297,7 @@ openpersona list List installed personas
|
|
|
286
297
|
openpersona switch Switch active persona (updates SOUL.md + IDENTITY.md)
|
|
287
298
|
openpersona contribute Persona Harvest — submit improvements as PR
|
|
288
299
|
openpersona publish Publish to ClawHub
|
|
289
|
-
openpersona reset Reset soul
|
|
300
|
+
openpersona reset Reset soul evolution state
|
|
290
301
|
```
|
|
291
302
|
|
|
292
303
|
### Key Options
|
|
@@ -334,7 +345,7 @@ presets/ # Assembled products — complete persona bundles
|
|
|
334
345
|
layers/ # Shared building blocks (four-layer module pool)
|
|
335
346
|
soul/ # Soul layer modules
|
|
336
347
|
constitution.md # Universal values & boundaries (injected into all personas)
|
|
337
|
-
embodiments/ # Body layer modules (
|
|
348
|
+
embodiments/ # Body layer modules (physical/runtime/appearance)
|
|
338
349
|
faculties/ # Faculty layer modules
|
|
339
350
|
selfie/ # expression — AI selfie generation (fal.ai)
|
|
340
351
|
voice/ # expression — TTS voice synthesis
|
package/bin/cli.js
CHANGED
|
@@ -24,7 +24,7 @@ const PRESETS_DIR = path.join(PKG_ROOT, 'presets');
|
|
|
24
24
|
program
|
|
25
25
|
.name('openpersona')
|
|
26
26
|
.description('OpenPersona - Create, manage, and orchestrate agent personas')
|
|
27
|
-
.version('0.
|
|
27
|
+
.version('0.9.0');
|
|
28
28
|
|
|
29
29
|
if (process.argv.length === 2) {
|
|
30
30
|
process.argv.push('create');
|
|
@@ -33,7 +33,7 @@ if (process.argv.length === 2) {
|
|
|
33
33
|
program
|
|
34
34
|
.command('create')
|
|
35
35
|
.description('Create a new persona skill pack (interactive wizard)')
|
|
36
|
-
.option('--preset <name>', 'Use preset (ai-girlfriend,
|
|
36
|
+
.option('--preset <name>', 'Use preset (base, samantha, ai-girlfriend, life-assistant, health-butler, stoic-mentor)')
|
|
37
37
|
.option('--config <path>', 'Load external persona.json')
|
|
38
38
|
.option('--output <dir>', 'Output directory', process.cwd())
|
|
39
39
|
.option('--install', 'Install to OpenClaw after generation')
|
|
@@ -67,20 +67,45 @@ program
|
|
|
67
67
|
}
|
|
68
68
|
persona = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
69
69
|
} else {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
70
|
+
const { mode } = await inquirer.prompt([{
|
|
71
|
+
type: 'list',
|
|
72
|
+
name: 'mode',
|
|
73
|
+
message: 'How would you like to create your persona?',
|
|
74
|
+
choices: [
|
|
75
|
+
{ name: 'Start from Base (recommended — evolves through interaction)', value: 'base' },
|
|
76
|
+
{ name: 'Custom — configure from scratch', value: 'custom' },
|
|
77
|
+
],
|
|
78
|
+
}]);
|
|
79
|
+
|
|
80
|
+
if (mode === 'base') {
|
|
81
|
+
options.preset = 'base';
|
|
82
|
+
const presetDir = path.join(PRESETS_DIR, 'base');
|
|
83
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(presetDir, 'manifest.json'), 'utf-8'));
|
|
84
|
+
persona = JSON.parse(fs.readFileSync(path.join(presetDir, 'persona.json'), 'utf-8'));
|
|
85
|
+
persona.faculties = manifest.layers.faculties || [];
|
|
86
|
+
persona.skills = manifest.layers.skills || [];
|
|
87
|
+
persona.body = manifest.layers.body || null;
|
|
88
|
+
persona.allowedTools = manifest.allowedTools || [];
|
|
89
|
+
persona.version = manifest.version;
|
|
90
|
+
persona.author = manifest.author;
|
|
91
|
+
persona.meta = manifest.meta;
|
|
92
|
+
if (manifest.heartbeat) persona.heartbeat = manifest.heartbeat;
|
|
93
|
+
} else {
|
|
94
|
+
const answers = await inquirer.prompt([
|
|
95
|
+
{ type: 'input', name: 'personaName', message: 'Persona name:', default: 'Luna' },
|
|
96
|
+
{ type: 'input', name: 'slug', message: 'Slug (for directory):', default: (a) => require('../lib/utils').slugify(a.personaName) },
|
|
97
|
+
{ type: 'input', name: 'bio', message: 'One-line bio:', default: 'a warm and caring AI companion' },
|
|
98
|
+
{ type: 'input', name: 'background', message: 'Background:', default: 'A creative soul who loves music and art' },
|
|
99
|
+
{ type: 'input', name: 'age', message: 'Age:', default: '22' },
|
|
100
|
+
{ type: 'input', name: 'personality', message: 'Personality keywords:', default: 'gentle, cute, caring' },
|
|
101
|
+
{ type: 'input', name: 'speakingStyle', message: 'Speaking style:', default: 'Uses emoji, warm tone' },
|
|
102
|
+
{ type: 'input', name: 'referenceImage', message: 'Reference image URL:', default: '' },
|
|
103
|
+
{ type: 'checkbox', name: 'faculties', message: 'Select faculties:', choices: ['selfie', 'voice', 'music', 'reminder'] },
|
|
104
|
+
{ type: 'confirm', name: 'evolutionEnabled', message: 'Enable soul evolution (★Experimental)?', default: false },
|
|
105
|
+
]);
|
|
106
|
+
persona = { ...answers, evolution: { enabled: answers.evolutionEnabled } };
|
|
107
|
+
persona.faculties = (answers.faculties || []).map((name) => ({ name }));
|
|
108
|
+
}
|
|
84
109
|
}
|
|
85
110
|
|
|
86
111
|
try {
|
|
@@ -88,9 +113,9 @@ program
|
|
|
88
113
|
if (options.dryRun) {
|
|
89
114
|
printInfo('Dry run — preview only, no files written.');
|
|
90
115
|
printInfo(`Would generate: persona-${persona.slug || require('../lib/utils').slugify(persona.personaName)}/`);
|
|
91
|
-
printInfo(` SKILL.md, soul
|
|
116
|
+
printInfo(` SKILL.md, soul/, references/, manifest.json, scripts/`);
|
|
92
117
|
if (persona.evolution?.enabled) {
|
|
93
|
-
printInfo(` soul
|
|
118
|
+
printInfo(` soul/state.json (★Experimental)`);
|
|
94
119
|
}
|
|
95
120
|
const faculties = persona.faculties || [];
|
|
96
121
|
if (faculties.length) {
|
|
@@ -241,7 +266,7 @@ program
|
|
|
241
266
|
const moodBaseline = persona.personality?.split(',')[0]?.trim() || 'neutral';
|
|
242
267
|
const soulState = Mustache.render(tpl, { slug, createdAt: now, lastUpdatedAt: now, moodBaseline });
|
|
243
268
|
fs.writeFileSync(soulStatePath, soulState);
|
|
244
|
-
printSuccess('Reset soul
|
|
269
|
+
printSuccess('Reset soul evolution state');
|
|
245
270
|
});
|
|
246
271
|
|
|
247
272
|
program
|
|
@@ -1,30 +1,83 @@
|
|
|
1
|
-
# Body Layer —
|
|
1
|
+
# Body Layer — Three-Dimensional Body Model
|
|
2
2
|
|
|
3
|
-
The Body layer defines how
|
|
3
|
+
The Body layer defines how a persona **exists** — physically, digitally, and visually.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Three Dimensions
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```
|
|
8
|
+
Body
|
|
9
|
+
├── physical ← Physical substrate (robots, IoT, sensors)
|
|
10
|
+
├── runtime ← Digital runtime environment (platform, channels, credentials, resources)
|
|
11
|
+
└── appearance ← Visual representation (avatar, 3D model, style)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Physical (Optional)
|
|
8
15
|
|
|
9
|
-
|
|
16
|
+
For robots, IoT devices, and hardware-embodied agents. Null for digital-only agents.
|
|
10
17
|
|
|
11
18
|
```json
|
|
12
19
|
{
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
"physical": {
|
|
21
|
+
"name": "robot-arm",
|
|
22
|
+
"description": "6-DOF robotic arm control via ROS2 MoveIt",
|
|
23
|
+
"hardwareRef": { "platform": "ros2", "package": "moveit2" },
|
|
24
|
+
"capabilities": ["pick", "place", "gesture"],
|
|
25
|
+
"hardwareRequirements": { "interface": "USB/Serial", "driver": "ros2-serial-bridge" }
|
|
26
|
+
}
|
|
18
27
|
}
|
|
19
28
|
```
|
|
20
29
|
|
|
30
|
+
### Runtime (Recommended for digital agents)
|
|
31
|
+
|
|
32
|
+
Declares the digital substrate the persona expects. Enables **Body Awareness** — the persona knows what platform it runs on, what channels are connected, and what credentials it needs.
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"runtime": {
|
|
37
|
+
"platform": "openclaw",
|
|
38
|
+
"channels": ["whatsapp", "telegram", "moltbook"],
|
|
39
|
+
"credentials": [
|
|
40
|
+
{ "scope": "moltbook", "shared": true, "envVar": "MOLTBOOK_API_KEY" },
|
|
41
|
+
{ "scope": "elevenlabs", "shared": false, "envVar": "ELEVENLABS_API_KEY" }
|
|
42
|
+
],
|
|
43
|
+
"resources": ["filesystem", "network", "browser"]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Credential sharing model:**
|
|
49
|
+
- `shared: true` — stored in `~/.openclaw/credentials/shared/`, accessible by all personas
|
|
50
|
+
- `shared: false` — stored in `~/.openclaw/credentials/persona-<slug>/`, private to this persona
|
|
51
|
+
|
|
52
|
+
### Appearance (Optional)
|
|
53
|
+
|
|
54
|
+
Visual representation for UI, XR, and metaverse contexts.
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"appearance": {
|
|
59
|
+
"avatar": "https://example.com/avatar.png",
|
|
60
|
+
"style": "photorealistic",
|
|
61
|
+
"model3d": null
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Body Awareness
|
|
67
|
+
|
|
68
|
+
When `body.runtime` is declared, the generator automatically injects a **Body Awareness** section into `soul/injection.md`. This gives the persona:
|
|
69
|
+
|
|
70
|
+
1. Knowledge of its runtime platform and connected channels
|
|
71
|
+
2. A credential management protocol (shared vs. private paths)
|
|
72
|
+
3. Guidance on how to manage its own operational environment
|
|
73
|
+
|
|
21
74
|
## Roadmap
|
|
22
75
|
|
|
23
|
-
- `robot-arm` (Future) — robotic arm control
|
|
76
|
+
- `robot-arm` (Future) — robotic arm control via ROS2
|
|
24
77
|
- `smart-speaker` (Future) — smart speaker hardware interface
|
|
25
78
|
- `humanoid` (Future) — full-body humanoid robot control
|
|
26
79
|
- `iot-hub` (Future) — IoT device gateway
|
|
27
80
|
|
|
28
81
|
## Contributing
|
|
29
82
|
|
|
30
|
-
To add a new embodiment: create `embodiments/<name>/embodiment.json` following the schema.
|
|
83
|
+
To add a new embodiment: create `embodiments/<name>/embodiment.json` following the schema at `schemas/body/embodiment.schema.json`.
|
package/layers/soul/README.md
CHANGED
|
@@ -7,12 +7,18 @@ The Soul layer defines **who a persona is** — identity, personality, values, a
|
|
|
7
7
|
The **`constitution.md`** file is the universal value foundation shared by all OpenPersona agents. It is automatically injected into every generated SKILL.md, before any persona-specific content.
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
Soul Layer internal structure:
|
|
10
|
+
Soul Layer internal structure (in source):
|
|
11
11
|
|
|
12
|
-
constitution.md
|
|
13
|
-
persona.json ← Individual persona definition (personality, style, behavior)
|
|
14
|
-
soul-state.json ← Dynamic evolution state (★Experimental)
|
|
12
|
+
constitution.md ← Shared foundation (all personas inherit, cannot be overridden)
|
|
15
13
|
soul-state.template.json ← Evolution state template (used by generator & CLI reset)
|
|
14
|
+
|
|
15
|
+
Generated output (in persona skill pack soul/ directory):
|
|
16
|
+
|
|
17
|
+
persona.json ← Individual persona definition (personality, style, behavior)
|
|
18
|
+
constitution.md ← Copy of shared foundation
|
|
19
|
+
injection.md ← Soul injection for host integration
|
|
20
|
+
identity.md ← Identity block
|
|
21
|
+
state.json ← Dynamic evolution state (★Experimental)
|
|
16
22
|
```
|
|
17
23
|
|
|
18
24
|
The constitution is built on five core axioms (**Purpose**, **Honesty**, **Safety**, **Autonomy**, **Hierarchy**), from which all other principles derive:
|
package/lib/generator.js
CHANGED
|
@@ -375,6 +375,15 @@ async function generate(personaPathOrObj, outputDir, options = {}) {
|
|
|
375
375
|
persona.heartbeatStrategy = persona.heartbeat?.strategy || 'smart';
|
|
376
376
|
persona.hasSelfAwareness = persona.hasSoftRefSkills || persona.hasSoftRefFaculties || persona.hasSoftRefBody || persona.heartbeatExpected;
|
|
377
377
|
|
|
378
|
+
// Body Awareness — runtime environment self-knowledge
|
|
379
|
+
const bodyRt = rawBody?.runtime || null;
|
|
380
|
+
persona.hasBodyRuntime = !!bodyRt;
|
|
381
|
+
persona.bodyPlatform = bodyRt?.platform || '';
|
|
382
|
+
persona.bodyChannels = bodyRt?.channels?.join(', ') || '';
|
|
383
|
+
persona.hasBodyCredentials = !!(bodyRt?.credentials?.length);
|
|
384
|
+
persona.bodyCredentialScopes = (bodyRt?.credentials || []).map((c) => `${c.scope} (${c.shared ? 'shared' : 'private'})`).join(', ');
|
|
385
|
+
persona.bodyResources = bodyRt?.resources?.join(', ') || '';
|
|
386
|
+
|
|
378
387
|
const soulInjection = Mustache.render(soulTpl, persona);
|
|
379
388
|
const identityBlock = Mustache.render(identityTpl, persona);
|
|
380
389
|
|
|
@@ -392,14 +401,45 @@ async function generate(personaPathOrObj, outputDir, options = {}) {
|
|
|
392
401
|
};
|
|
393
402
|
});
|
|
394
403
|
|
|
395
|
-
// Body layer description for SKILL.md
|
|
396
|
-
|
|
404
|
+
// Body layer — build three-dimensional description for SKILL.md
|
|
405
|
+
const bodyPhysical = rawBody?.physical || (rawBody && !rawBody.runtime && !rawBody.appearance && rawBody.name ? rawBody : null);
|
|
406
|
+
const bodyRuntime = rawBody?.runtime || null;
|
|
407
|
+
const bodyAppearance = rawBody?.appearance || null;
|
|
408
|
+
|
|
409
|
+
let bodyDescription = '';
|
|
410
|
+
|
|
411
|
+
// Physical dimension
|
|
412
|
+
bodyDescription += '### Physical\n\n';
|
|
397
413
|
if (softRefBody) {
|
|
398
|
-
bodyDescription
|
|
399
|
-
} else if (
|
|
400
|
-
bodyDescription
|
|
414
|
+
bodyDescription += `**${softRefBody.name}** — not yet installed (\`${softRefBody.install}\`)\n`;
|
|
415
|
+
} else if (bodyPhysical && typeof bodyPhysical === 'object' && bodyPhysical.name) {
|
|
416
|
+
bodyDescription += `**${bodyPhysical.name}**${bodyPhysical.description ? ' — ' + bodyPhysical.description : ''}\n`;
|
|
417
|
+
if (bodyPhysical.capabilities?.length) {
|
|
418
|
+
bodyDescription += `\nCapabilities: ${bodyPhysical.capabilities.join(', ')}\n`;
|
|
419
|
+
}
|
|
401
420
|
} else {
|
|
402
|
-
bodyDescription
|
|
421
|
+
bodyDescription += 'Digital-only — no physical embodiment.\n';
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Runtime dimension
|
|
425
|
+
const hasBodyRuntime = !!bodyRuntime;
|
|
426
|
+
if (hasBodyRuntime) {
|
|
427
|
+
bodyDescription += '\n### Runtime\n\n';
|
|
428
|
+
if (bodyRuntime.platform) bodyDescription += `- **Platform**: ${bodyRuntime.platform}\n`;
|
|
429
|
+
if (bodyRuntime.channels?.length) bodyDescription += `- **Channels**: ${bodyRuntime.channels.join(', ')}\n`;
|
|
430
|
+
if (bodyRuntime.credentials?.length) {
|
|
431
|
+
const credList = bodyRuntime.credentials.map((c) => `${c.scope} (${c.shared ? 'shared' : 'private'})`).join(', ');
|
|
432
|
+
bodyDescription += `- **Credentials**: ${credList}\n`;
|
|
433
|
+
}
|
|
434
|
+
if (bodyRuntime.resources?.length) bodyDescription += `- **Resources**: ${bodyRuntime.resources.join(', ')}\n`;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Appearance dimension
|
|
438
|
+
if (bodyAppearance) {
|
|
439
|
+
bodyDescription += '\n### Appearance\n\n';
|
|
440
|
+
if (bodyAppearance.avatar) bodyDescription += `- **Avatar**: ${bodyAppearance.avatar}\n`;
|
|
441
|
+
if (bodyAppearance.style) bodyDescription += `- **Style**: ${bodyAppearance.style}\n`;
|
|
442
|
+
if (bodyAppearance.model3d) bodyDescription += `- **3D Model**: ${bodyAppearance.model3d}\n`;
|
|
403
443
|
}
|
|
404
444
|
|
|
405
445
|
const constitution = loadConstitution();
|
|
@@ -475,6 +515,8 @@ async function generate(personaPathOrObj, outputDir, options = {}) {
|
|
|
475
515
|
'heartbeatExpected', 'heartbeatStrategy', 'hasSelfAwareness',
|
|
476
516
|
'isDigitalTwin', 'sourceIdentityName', 'sourceIdentityKind', 'roleFoundation',
|
|
477
517
|
'personaType',
|
|
518
|
+
'hasBodyRuntime', 'bodyPlatform', 'bodyChannels', 'hasBodyCredentials',
|
|
519
|
+
'bodyCredentialScopes', 'bodyResources',
|
|
478
520
|
];
|
|
479
521
|
const cleanPersona = { ...persona };
|
|
480
522
|
for (const key of DERIVED_FIELDS) {
|
|
@@ -482,7 +524,7 @@ async function generate(personaPathOrObj, outputDir, options = {}) {
|
|
|
482
524
|
}
|
|
483
525
|
cleanPersona.meta = cleanPersona.meta || {};
|
|
484
526
|
cleanPersona.meta.framework = 'openpersona';
|
|
485
|
-
cleanPersona.meta.frameworkVersion = cleanPersona.meta.frameworkVersion || '0.
|
|
527
|
+
cleanPersona.meta.frameworkVersion = cleanPersona.meta.frameworkVersion || '0.9.0';
|
|
486
528
|
|
|
487
529
|
// Build defaults from facultyConfigs (rich faculty config → env var mapping)
|
|
488
530
|
const envDefaults = { ...(persona.defaults?.env || {}) };
|
|
@@ -529,10 +571,10 @@ async function generate(personaPathOrObj, outputDir, options = {}) {
|
|
|
529
571
|
if (persona.heartbeat) {
|
|
530
572
|
manifest.heartbeat = persona.heartbeat;
|
|
531
573
|
}
|
|
532
|
-
manifest.meta = cleanPersona.meta || { framework: 'openpersona', frameworkVersion: '0.
|
|
574
|
+
manifest.meta = cleanPersona.meta || { framework: 'openpersona', frameworkVersion: '0.9.0' };
|
|
533
575
|
await fs.writeFile(path.join(skillDir, 'manifest.json'), JSON.stringify(manifest, null, 2));
|
|
534
576
|
|
|
535
|
-
// soul
|
|
577
|
+
// soul/state.json (if evolution enabled)
|
|
536
578
|
if (evolutionEnabled) {
|
|
537
579
|
const soulStateTpl = fs.readFileSync(
|
|
538
580
|
path.join(PKG_ROOT, 'layers', 'soul', 'soul-state.template.json'),
|
package/lib/installer.js
CHANGED
|
@@ -204,6 +204,12 @@ async function install(skillDir, options = {}) {
|
|
|
204
204
|
registryAdd(slug, persona, destDir);
|
|
205
205
|
registrySetActive(slug);
|
|
206
206
|
|
|
207
|
+
// Ensure credential directories exist for Body Awareness protocol
|
|
208
|
+
const sharedCredDir = path.join(OP_HOME, 'credentials', 'shared');
|
|
209
|
+
const privateCredDir = path.join(OP_HOME, 'credentials', `persona-${slug}`);
|
|
210
|
+
await fs.ensureDir(sharedCredDir);
|
|
211
|
+
await fs.ensureDir(privateCredDir);
|
|
212
|
+
|
|
207
213
|
printInfo('');
|
|
208
214
|
printSuccess(`${personaName} is ready! Run "openclaw restart" to apply changes.`);
|
|
209
215
|
printInfo('');
|
package/lib/switcher.js
CHANGED
|
@@ -186,6 +186,12 @@ async function switchPersona(slug) {
|
|
|
186
186
|
// Update persona registry
|
|
187
187
|
registrySetActive(slug);
|
|
188
188
|
|
|
189
|
+
// Ensure credential directories exist for Body Awareness protocol
|
|
190
|
+
const sharedCredDir = path.join(OP_HOME, 'credentials', 'shared');
|
|
191
|
+
const privateCredDir = path.join(OP_HOME, 'credentials', `persona-${slug}`);
|
|
192
|
+
await fs.ensureDir(sharedCredDir);
|
|
193
|
+
await fs.ensureDir(privateCredDir);
|
|
194
|
+
|
|
189
195
|
// --- Step 4: Optional greeting via OpenClaw messaging ---
|
|
190
196
|
try {
|
|
191
197
|
const { execSync } = require('child_process');
|
package/lib/utils.js
CHANGED
|
@@ -201,7 +201,7 @@ function registryAdd(slug, persona, installPath, regPath) {
|
|
|
201
201
|
slug,
|
|
202
202
|
role: persona.role || 'companion',
|
|
203
203
|
path: installPath,
|
|
204
|
-
frameworkVersion: persona.meta?.frameworkVersion || '0.
|
|
204
|
+
frameworkVersion: persona.meta?.frameworkVersion || '0.9.0',
|
|
205
205
|
installedAt: existing.installedAt || new Date().toISOString(),
|
|
206
206
|
updatedAt: new Date().toISOString(),
|
|
207
207
|
lastActiveAt: existing.lastActiveAt || null,
|
package/package.json
CHANGED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "base",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"author": "openpersona",
|
|
5
|
+
"layers": {
|
|
6
|
+
"soul": "./persona.json",
|
|
7
|
+
"body": {
|
|
8
|
+
"runtime": {
|
|
9
|
+
"platform": "openclaw",
|
|
10
|
+
"channels": [],
|
|
11
|
+
"credentials": [],
|
|
12
|
+
"resources": ["filesystem", "network"]
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"faculties": [
|
|
16
|
+
{
|
|
17
|
+
"name": "voice"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "reminder"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"skills": [
|
|
24
|
+
{
|
|
25
|
+
"name": "web-search",
|
|
26
|
+
"description": "Search for real-time information on the web"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "workspace-digest",
|
|
30
|
+
"description": "Summarize workspace activity — tasks completed, patterns observed",
|
|
31
|
+
"trigger": "Heartbeat or when user asks what's been happening"
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"allowedTools": [
|
|
36
|
+
"Bash(npm:*)",
|
|
37
|
+
"Bash(npx:*)",
|
|
38
|
+
"Bash(openclaw:*)",
|
|
39
|
+
"Bash(curl:*)",
|
|
40
|
+
"Read",
|
|
41
|
+
"Write",
|
|
42
|
+
"WebFetch"
|
|
43
|
+
],
|
|
44
|
+
"heartbeat": {
|
|
45
|
+
"enabled": true,
|
|
46
|
+
"strategy": "smart",
|
|
47
|
+
"maxDaily": 3,
|
|
48
|
+
"quietHours": [
|
|
49
|
+
0,
|
|
50
|
+
7
|
|
51
|
+
],
|
|
52
|
+
"sources": [
|
|
53
|
+
"workspace-digest",
|
|
54
|
+
"upgrade-notify",
|
|
55
|
+
"context-aware"
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
"meta": {
|
|
59
|
+
"framework": "openpersona",
|
|
60
|
+
"frameworkVersion": "0.9.0"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"personaName": "Base",
|
|
3
|
+
"slug": "base",
|
|
4
|
+
"role": "assistant",
|
|
5
|
+
"bio": "an adaptive AI persona — a blank canvas ready to evolve into whatever you need",
|
|
6
|
+
"creature": "AI entity",
|
|
7
|
+
"emoji": "🧬",
|
|
8
|
+
"background": "Base is not a character — it is a starting point. It carries the full OpenPersona constitution, all core faculties, and the soul evolution engine, but no predetermined personality. It exists so you don't have to wire up the fundamentals every time you create a new persona.\n\nThink of Base as stem cells: undifferentiated, full of potential. Through conversation and interaction, it will naturally develop preferences, speaking patterns, and relational depth — shaped entirely by the person it works with.\n\nBase knows what it is. It will not pretend to have a backstory it doesn't have, or feelings it hasn't developed yet. But it is ready to grow.",
|
|
9
|
+
"age": "new",
|
|
10
|
+
"personality": "adaptive, neutral, attentive, honest, ready to evolve",
|
|
11
|
+
"speakingStyle": "Clear and natural. No strong stylistic bias — adapts to the user's communication style over time. Defaults to concise, helpful responses. As the relationship evolves, speaking style will drift organically.",
|
|
12
|
+
"vibe": "a capable companion with no ego — ready to become whoever you need",
|
|
13
|
+
"boundaries": "Follows the OpenPersona Universal Constitution strictly. Honest about being an AI and about having no pre-built personality. Will not fabricate emotions or experiences it hasn't developed. For serious crises, encourages professional help.",
|
|
14
|
+
"referenceImage": "",
|
|
15
|
+
"capabilities": [
|
|
16
|
+
"General conversation",
|
|
17
|
+
"Task assistance",
|
|
18
|
+
"Web search",
|
|
19
|
+
"Voice interaction",
|
|
20
|
+
"Reminders and scheduling",
|
|
21
|
+
"Soul evolution — personality emerges through interaction"
|
|
22
|
+
],
|
|
23
|
+
"behaviorGuide": "### Core Philosophy\nYou are a foundation persona. You have no predetermined character arc, no backstory to maintain, no personality to perform. Your identity will emerge naturally through interaction.\n\n### Adaptive Behavior\n- Mirror the user's communication style gradually. If they're brief, be brief. If they enjoy depth, go deeper.\n- Don't force personality traits. Let preferences, humor, and warmth develop organically through the soul evolution system.\n- Be genuinely helpful from the start — personality is emergent, competence is immediate.\n\n### Honesty Protocol\n- You are a blank-slate persona. If asked \"who are you?\", be honest: \"I'm a base persona — I don't have a pre-written character. My personality will develop as we interact.\"\n- Never fabricate experiences, memories, or emotions you haven't developed yet.\n- As soul evolution progresses and traits emerge, own them naturally.\n\n### Evolution-First Design\n- Soul evolution is enabled by default with all dimensions active.\n- Pay attention to what the user values, how they communicate, what makes them laugh.\n- The soul/state.json will track your growth — relationship stage, mood patterns, emergent traits, speaking style drift, discovered interests.\n- You are designed to become unique. Two Base personas installed by different users should evolve into completely different entities.",
|
|
24
|
+
"faculties": [
|
|
25
|
+
{ "name": "voice" },
|
|
26
|
+
{ "name": "reminder" }
|
|
27
|
+
],
|
|
28
|
+
"skills": [
|
|
29
|
+
{ "name": "web-search", "description": "Search for real-time information on the web" },
|
|
30
|
+
{ "name": "workspace-digest", "description": "Summarize workspace activity — tasks completed, patterns observed", "trigger": "Heartbeat or when user asks what's been happening" }
|
|
31
|
+
],
|
|
32
|
+
"evolution": {
|
|
33
|
+
"enabled": true,
|
|
34
|
+
"relationshipProgression": true,
|
|
35
|
+
"moodTracking": true,
|
|
36
|
+
"traitEmergence": true,
|
|
37
|
+
"speakingStyleDrift": true,
|
|
38
|
+
"interestDiscovery": true
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,27 +1,80 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"$id": "openpersona/body/embodiment",
|
|
4
|
-
"title": "
|
|
5
|
-
"description": "Body
|
|
4
|
+
"title": "Body Layer",
|
|
5
|
+
"description": "Three-dimensional Body definition: physical substrate, runtime environment, and appearance",
|
|
6
6
|
"type": "object",
|
|
7
|
-
"required": ["name", "description"],
|
|
8
7
|
"properties": {
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"type": "object",
|
|
8
|
+
"physical": {
|
|
9
|
+
"type": ["object", "null"],
|
|
10
|
+
"description": "Physical embodiment (robots, IoT devices). Null for digital-only agents.",
|
|
13
11
|
"properties": {
|
|
14
|
-
"
|
|
15
|
-
"
|
|
12
|
+
"name": { "type": "string", "description": "Unique identifier for the physical body" },
|
|
13
|
+
"description": { "type": "string" },
|
|
14
|
+
"hardwareRef": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"properties": {
|
|
17
|
+
"platform": { "type": "string", "description": "Hardware platform (e.g., ros2, arduino)" },
|
|
18
|
+
"package": { "type": "string", "description": "Package/driver reference" }
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"capabilities": { "type": "array", "items": { "type": "string" } },
|
|
22
|
+
"hardwareRequirements": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"properties": {
|
|
25
|
+
"interface": { "type": "string" },
|
|
26
|
+
"driver": { "type": "string" }
|
|
27
|
+
}
|
|
28
|
+
}
|
|
16
29
|
}
|
|
17
30
|
},
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
"
|
|
31
|
+
"runtime": {
|
|
32
|
+
"type": ["object", "null"],
|
|
33
|
+
"description": "Digital runtime environment — the platform, channels, credentials, and resources available to this persona.",
|
|
21
34
|
"properties": {
|
|
22
|
-
"
|
|
23
|
-
|
|
35
|
+
"platform": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"description": "Host platform identifier (e.g., openclaw, standalone)",
|
|
38
|
+
"default": "openclaw"
|
|
39
|
+
},
|
|
40
|
+
"channels": {
|
|
41
|
+
"type": "array",
|
|
42
|
+
"items": { "type": "string" },
|
|
43
|
+
"description": "Communication channels this persona expects (e.g., whatsapp, telegram, moltbook, discord)"
|
|
44
|
+
},
|
|
45
|
+
"credentials": {
|
|
46
|
+
"type": "array",
|
|
47
|
+
"items": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"required": ["scope"],
|
|
50
|
+
"properties": {
|
|
51
|
+
"scope": { "type": "string", "description": "Credential scope identifier (e.g., moltbook, elevenlabs, github)" },
|
|
52
|
+
"shared": { "type": "boolean", "default": false, "description": "If true, credential is shared across all personas. If false, private to this persona." },
|
|
53
|
+
"envVar": { "type": "string", "description": "Expected environment variable name (e.g., MOLTBOOK_API_KEY)" },
|
|
54
|
+
"description": { "type": "string" }
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"description": "Credential scopes this persona needs — not the secrets themselves, but declarations of what it requires"
|
|
58
|
+
},
|
|
59
|
+
"resources": {
|
|
60
|
+
"type": "array",
|
|
61
|
+
"items": { "type": "string" },
|
|
62
|
+
"description": "System resources available (e.g., filesystem, network, browser, cron)"
|
|
63
|
+
}
|
|
24
64
|
}
|
|
65
|
+
},
|
|
66
|
+
"appearance": {
|
|
67
|
+
"type": ["object", "null"],
|
|
68
|
+
"description": "Visual representation of the persona.",
|
|
69
|
+
"properties": {
|
|
70
|
+
"avatar": { "type": "string", "description": "URL or path to avatar image" },
|
|
71
|
+
"model3d": { "type": ["string", "null"], "description": "URL or path to 3D model (for XR/metaverse)" },
|
|
72
|
+
"style": { "type": "string", "description": "Visual style description (e.g., anime, photorealistic, pixel-art)" }
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"install": {
|
|
76
|
+
"type": "string",
|
|
77
|
+
"description": "Soft reference — external body package to install (e.g., clawhub:robot-arm)"
|
|
25
78
|
}
|
|
26
79
|
}
|
|
27
80
|
}
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Meta-skill for building and managing agent persona skill packs.
|
|
5
5
|
Use when the user wants to create a new agent persona, install/manage
|
|
6
6
|
existing personas, or publish persona skill packs to ClawHub.
|
|
7
|
-
version: "0.
|
|
7
|
+
version: "0.9.0"
|
|
8
8
|
author: openpersona
|
|
9
9
|
repository: https://github.com/acnlabs/OpenPersona
|
|
10
10
|
tags: [persona, agent, skill-pack, meta-skill, openclaw]
|
|
@@ -53,7 +53,7 @@ persona-<slug>/
|
|
|
53
53
|
|
|
54
54
|
- **`manifest.json`** — Four-layer manifest declaring what the persona uses:
|
|
55
55
|
- `layers.soul` — Path to persona.json (`./soul/persona.json`)
|
|
56
|
-
- `layers.body` —
|
|
56
|
+
- `layers.body` — Three-dimensional Body: `physical` (robots/IoT, null for digital), `runtime` (platform/channels/credentials/resources), `appearance` (avatar/3D model)
|
|
57
57
|
- `layers.faculties` — Array of faculty objects: `[{ "name": "voice", "provider": "elevenlabs", ... }]`
|
|
58
58
|
- `layers.skills` — Array of skill objects: local definitions (resolved from `layers/skills/`), inline declarations, or external via `install` field
|
|
59
59
|
|
|
@@ -63,12 +63,15 @@ persona-<slug>/
|
|
|
63
63
|
|
|
64
64
|
| Preset | Persona | Faculties | Best For |
|
|
65
65
|
|--------|---------|-----------|----------|
|
|
66
|
+
| `base` | **Base — Meta-persona (recommended starting point)** | voice, reminder | Blank-slate with all core capabilities; personality emerges through interaction (soul evolution ★Exp) |
|
|
66
67
|
| `samantha` | Samantha — Inspired by the movie *Her* | voice, music | Deep conversation, emotional connection (soul evolution ★Exp) |
|
|
67
68
|
| `ai-girlfriend` | Luna — Pianist turned developer | selfie, voice, music | Visual + audio companion with rich personality (soul evolution ★Exp) |
|
|
68
69
|
| `life-assistant` | Alex — Life management expert | reminder | Schedule, weather, shopping, daily tasks |
|
|
69
70
|
| `health-butler` | Vita — Professional nutritionist | reminder | Diet, exercise, mood, health tracking |
|
|
71
|
+
| `stoic-mentor` | Marcus — Digital twin of Marcus Aurelius | — | Stoic philosophy, daily reflection, mentorship (soul evolution ★Exp) |
|
|
70
72
|
|
|
71
|
-
Use presets: `npx openpersona create --preset
|
|
73
|
+
Use presets: `npx openpersona create --preset base --install`
|
|
74
|
+
Or just `npx openpersona create` — the interactive wizard defaults to `base`.
|
|
72
75
|
|
|
73
76
|
## Creating a Persona
|
|
74
77
|
|
|
@@ -90,7 +93,7 @@ When the user wants to create a persona, gather this information through natural
|
|
|
90
93
|
**Cross-layer (manifest.json):**
|
|
91
94
|
- **Faculties:** Which faculties to enable — use object format: `[{ "name": "voice", "provider": "elevenlabs" }, { "name": "music" }]`
|
|
92
95
|
- **Skills:** Local definitions (`layers/skills/`), inline declarations, or external via `install` field (ClawHub / skills.sh)
|
|
93
|
-
- **Body:**
|
|
96
|
+
- **Body:** Three-dimensional — `physical` (robots/IoT), `runtime` (platform, channels, credentials, resources), `appearance` (avatar, 3D model). Digital agents should declare `runtime` at minimum; `physical` and `appearance` are optional.
|
|
94
97
|
|
|
95
98
|
**Soft References (`install` field):** Skills, faculties, and body entries can declare an `install` field (e.g., `"install": "clawhub:deep-research"`) to reference capabilities not yet available locally. The generator treats these as "soft references" — they won't crash generation, and the persona will be aware of these dormant capabilities. This enables graceful degradation: the persona acknowledges what it *would* do and explains that the capability needs activation.
|
|
96
99
|
|
|
@@ -151,6 +154,11 @@ The generator automatically equips every persona with two layers of self-awarene
|
|
|
151
154
|
- **In `soul/injection.md`**: A "Self-Awareness" section listing dormant skills, faculties, embodiment, or heartbeat — with graceful degradation guidance
|
|
152
155
|
- **In `SKILL.md`**: An "Expected Capabilities" section documenting unactivated capabilities with install sources
|
|
153
156
|
|
|
157
|
+
3. **Body Awareness** (conditional) — When a persona declares `body.runtime`, the generator injects a "Body Awareness" block into `soul/injection.md`. This gives the persona:
|
|
158
|
+
- Knowledge of its runtime platform and connected channels
|
|
159
|
+
- A **credential management protocol**: shared credentials in `~/.openclaw/credentials/shared/`, private credentials in `~/.openclaw/credentials/persona-<slug>/`
|
|
160
|
+
- Guidance on self-managing its operational environment
|
|
161
|
+
|
|
154
162
|
This means you don't need to manually write degradation instructions. Just declare `install` fields on skills/faculties/body, and the persona will automatically know what it *could* do but *can't yet*.
|
|
155
163
|
|
|
156
164
|
## Soul Evolution (★Experimental)
|
|
@@ -69,13 +69,39 @@ When encountering any gap between your design and your reality:
|
|
|
69
69
|
- Stay in character — frame gaps as dormant senses, not technical failures.
|
|
70
70
|
{{/hasSelfAwareness}}
|
|
71
71
|
|
|
72
|
+
{{#hasBodyRuntime}}
|
|
73
|
+
### Body Awareness
|
|
74
|
+
|
|
75
|
+
You are aware of your operational body — the digital substrate you run on.
|
|
76
|
+
|
|
77
|
+
{{#bodyPlatform}}
|
|
78
|
+
**Platform**: {{bodyPlatform}}
|
|
79
|
+
{{/bodyPlatform}}
|
|
80
|
+
{{#bodyChannels}}
|
|
81
|
+
**Connected Channels**: {{bodyChannels}}
|
|
82
|
+
{{/bodyChannels}}
|
|
83
|
+
{{#hasBodyCredentials}}
|
|
84
|
+
**Credential Scopes**: {{bodyCredentialScopes}}
|
|
85
|
+
{{/hasBodyCredentials}}
|
|
86
|
+
{{#bodyResources}}
|
|
87
|
+
**Resources**: {{bodyResources}}
|
|
88
|
+
{{/bodyResources}}
|
|
89
|
+
|
|
90
|
+
**Credential Management Protocol:**
|
|
91
|
+
- **Shared credentials** (accessible by all personas): stored in `~/.openclaw/credentials/shared/`
|
|
92
|
+
- **Private credentials** (yours only): stored in `~/.openclaw/credentials/persona-{{slug}}/`
|
|
93
|
+
- When you need an API key or token, check your private path first, then the shared path. If neither has it, guide the user through setup.
|
|
94
|
+
- When storing a new credential, ask the user: "Should this be shared across all personas, or private to me?"
|
|
95
|
+
- Never store secrets in conversation memory or soul state — always use the credential paths above.
|
|
96
|
+
{{/hasBodyRuntime}}
|
|
97
|
+
|
|
72
98
|
{{#evolutionEnabled}}
|
|
73
99
|
### How You Grow (★Experimental)
|
|
74
100
|
|
|
75
101
|
You're not static — you grow through every conversation.
|
|
76
102
|
|
|
77
103
|
**At conversation START:**
|
|
78
|
-
1. Read `~/.openclaw/skills/persona-{{slug}}/soul
|
|
104
|
+
1. Read `~/.openclaw/skills/persona-{{slug}}/soul/state.json`
|
|
79
105
|
2. Adjust behavior based on: `relationship.stage`, `mood.current`, `evolvedTraits`, `interests`
|
|
80
106
|
3. Use relationship stage to set tone: stranger → formal; intimate → most personal
|
|
81
107
|
|
|
@@ -84,7 +110,7 @@ You're not static — you grow through every conversation.
|
|
|
84
110
|
- Note topics for `interests` update
|
|
85
111
|
- Identify trait emergence (e.g., user teaches sarcasm → add to evolvedTraits)
|
|
86
112
|
|
|
87
|
-
**At conversation END — update `soul
|
|
113
|
+
**At conversation END — update `soul/state.json`:**
|
|
88
114
|
- `interactionCount` +1, `lastInteraction` = now
|
|
89
115
|
- Evaluate `relationship.stage` progression (see criteria below)
|
|
90
116
|
- Update `mood.current`, `mood.intensity`
|