openpersona 0.8.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 CHANGED
@@ -51,7 +51,9 @@ flowchart TB
51
51
  B["state.json — Dynamic evolution"]
52
52
  end
53
53
  subgraph Body ["Body Layer"]
54
- C["embodiment.jsonMVP placeholder"]
54
+ C["physicalrobots/IoT"]
55
+ G["runtime — platform/channels/credentials"]
56
+ H["appearance — avatar/3D model"]
55
57
  end
56
58
  subgraph Faculty ["Faculty Layer"]
57
59
  D["expression: selfie · voice · music"]
@@ -63,7 +65,7 @@ flowchart TB
63
65
  ```
64
66
 
65
67
  - **Soul** — Persona definition (constitution.md + persona.json + state.json) — all in `soul/` directory
66
- - **Body** — Physical embodiment (MVP placeholder, for robots/IoT devices)
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.
67
69
  - **Faculty** — General software capabilities organized by dimension: Expression, Sense, Cognition
68
70
  - **Skill** — Professional skills: local definitions in `layers/skills/`, or external via ClawHub / skills.sh (`install` field)
69
71
 
@@ -343,7 +345,7 @@ presets/ # Assembled products — complete persona bundles
343
345
  layers/ # Shared building blocks (four-layer module pool)
344
346
  soul/ # Soul layer modules
345
347
  constitution.md # Universal values & boundaries (injected into all personas)
346
- embodiments/ # Body layer modules (MVP placeholder)
348
+ embodiments/ # Body layer modules (physical/runtime/appearance)
347
349
  faculties/ # Faculty layer modules
348
350
  selfie/ # expression — AI selfie generation (fal.ai)
349
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.8.0');
27
+ .version('0.9.0');
28
28
 
29
29
  if (process.argv.length === 2) {
30
30
  process.argv.push('create');
@@ -1,30 +1,83 @@
1
- # Body Layer — Physical Embodiment
1
+ # Body Layer — Three-Dimensional Body Model
2
2
 
3
- The Body layer defines how an agent exists in the **physical world**: robots, IoT devices, hardware sensors/actuators.
3
+ The Body layer defines how a persona **exists** physically, digitally, and visually.
4
4
 
5
- **Pure digital agents have no Body** — chatbot does not need physical embodiment.
5
+ ## Three Dimensions
6
6
 
7
- ## embodiment.json Standard (MVP — Reserved)
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
- See `schemas/body/embodiment.schema.json` for the schema.
16
+ For robots, IoT devices, and hardware-embodied agents. Null for digital-only agents.
10
17
 
11
18
  ```json
12
19
  {
13
- "name": "robot-arm",
14
- "hardwareRef": { "platform": "ros2", "package": "moveit2" },
15
- "description": "6-DOF robotic arm control via ROS2 MoveIt",
16
- "capabilities": ["pick", "place", "gesture"],
17
- "hardwareRequirements": { "interface": "USB/Serial", "driver": "ros2-serial-bridge" }
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/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
- let bodyDescription;
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 = `**${softRefBody.name}** — not yet installed (\`${softRefBody.install}\`)`;
399
- } else if (rawBody && typeof rawBody === 'object' && rawBody.name) {
400
- bodyDescription = `**${rawBody.name}**${rawBody.description ? ' — ' + rawBody.description : ''}`;
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 = 'Digital-only — no physical embodiment.';
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.8.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,7 +571,7 @@ 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.8.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
577
  // soul/state.json (if evolution enabled)
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.8.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openpersona",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Open four-layer agent framework — Soul/Body/Faculty/Skill. Create, manage, and orchestrate agent personas.",
5
5
  "main": "lib/generator.js",
6
6
  "bin": {
@@ -57,6 +57,6 @@
57
57
  },
58
58
  "meta": {
59
59
  "framework": "openpersona",
60
- "frameworkVersion": "0.8.0"
60
+ "frameworkVersion": "0.9.0"
61
61
  }
62
62
  }
@@ -4,7 +4,14 @@
4
4
  "author": "openpersona",
5
5
  "layers": {
6
6
  "soul": "./persona.json",
7
- "body": null,
7
+ "body": {
8
+ "runtime": {
9
+ "platform": "openclaw",
10
+ "channels": [],
11
+ "credentials": [],
12
+ "resources": ["filesystem", "network"]
13
+ }
14
+ },
8
15
  "faculties": [
9
16
  {
10
17
  "name": "voice"
@@ -50,6 +57,6 @@
50
57
  },
51
58
  "meta": {
52
59
  "framework": "openpersona",
53
- "frameworkVersion": "0.8.0"
60
+ "frameworkVersion": "0.9.0"
54
61
  }
55
62
  }
@@ -62,6 +62,6 @@
62
62
  },
63
63
  "meta": {
64
64
  "framework": "openpersona",
65
- "frameworkVersion": "0.8.0"
65
+ "frameworkVersion": "0.9.0"
66
66
  }
67
67
  }
@@ -61,6 +61,6 @@
61
61
  },
62
62
  "meta": {
63
63
  "framework": "openpersona",
64
- "frameworkVersion": "0.8.0"
64
+ "frameworkVersion": "0.9.0"
65
65
  }
66
66
  }
@@ -64,6 +64,6 @@
64
64
  },
65
65
  "meta": {
66
66
  "framework": "openpersona",
67
- "frameworkVersion": "0.8.0"
67
+ "frameworkVersion": "0.9.0"
68
68
  }
69
69
  }
@@ -43,6 +43,6 @@
43
43
  },
44
44
  "meta": {
45
45
  "framework": "openpersona",
46
- "frameworkVersion": "0.8.0"
46
+ "frameworkVersion": "0.9.0"
47
47
  }
48
48
  }
@@ -1,27 +1,80 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "openpersona/body/embodiment",
4
- "title": "Embodiment",
5
- "description": "Body layer - Physical embodiment definition",
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
- "name": { "type": "string", "description": "Unique identifier" },
10
- "description": { "type": "string" },
11
- "hardwareRef": {
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
- "platform": { "type": "string" },
15
- "package": { "type": "string" }
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
- "capabilities": { "type": "array", "items": { "type": "string" } },
19
- "hardwareRequirements": {
20
- "type": "object",
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
- "interface": { "type": "string" },
23
- "driver": { "type": "string" }
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.8.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` — Physical embodiment (null for digital agents)
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
 
@@ -93,7 +93,7 @@ When the user wants to create a persona, gather this information through natural
93
93
  **Cross-layer (manifest.json):**
94
94
  - **Faculties:** Which faculties to enable — use object format: `[{ "name": "voice", "provider": "elevenlabs" }, { "name": "music" }]`
95
95
  - **Skills:** Local definitions (`layers/skills/`), inline declarations, or external via `install` field (ClawHub / skills.sh)
96
- - **Body:** Physical embodiment (null for most personas, or object with `install` for external embodiment)
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.
97
97
 
98
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.
99
99
 
@@ -154,6 +154,11 @@ The generator automatically equips every persona with two layers of self-awarene
154
154
  - **In `soul/injection.md`**: A "Self-Awareness" section listing dormant skills, faculties, embodiment, or heartbeat — with graceful degradation guidance
155
155
  - **In `SKILL.md`**: An "Expected Capabilities" section documenting unactivated capabilities with install sources
156
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
+
157
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*.
158
163
 
159
164
  ## Soul Evolution (★Experimental)
@@ -69,6 +69,32 @@ 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