identity.yaml field reference, see Identity Manifest.
Identity Structure
An identity is a self-contained directory with anidentity.yaml manifest and workspace files:
Step 1: Create identity.yaml
Start with the required fields:
Step 2: Write Workspace Files
SOUL.md — Personality
The most important file. It shapes how the agent thinks and communicates. Define:- Core truths — fundamental principles that guide behavior
- Superpowers — what this agent excels at
- Boundaries — what the agent should avoid or defer on
- Vibe — one-line personality summary
- Continuity — remind the agent that these files are its memory
IDENTITY.md — Name Card
Short file with the agent’s name, role, emoji, and a one-line role description. Keep it to 5-10 lines.HEARTBEAT.md — Periodic Tasks
A checklist the agent runs on each heartbeat cycle (every minute). Always include a bootstrap check at the top:TOOLS.md — Tool Reference
A cheat sheet for the tools available to the agent:AGENTS.md — Operational Instructions
Shared instructions for multi-agent coordination. Covers session startup, memory management, safety rules, and heartbeat behavior. You can use the example AGENTS.md as a starting point.BOOTSTRAP.md — First-Run Setup
Integration checks that run once when the agent is first deployed. Verify each tool and plugin works, then delete the file. If any check fails, the file stays and the agent reports the failure.USER.md — Owner Info
Templated file with the agent owner’s details:Step 3: Create Skills
Skills are reusable workflows. Each skill lives inskills/<skill-name>/SKILL.md with YAML frontmatter:
Frontmatter Fields
| Field | Required | Description |
|---|---|---|
name | Yes | Skill identifier |
description | Yes | One-line summary |
metadata | No | JSON string — openclaw.emoji sets UI icon, openclaw.requires.bins declares binary deps |
user-invocable | No | Whether users can trigger directly (default: true). Set false for system-triggered skills like queue handlers. |
Private vs Public Skills
Step 4: Use Your Identity
During Development (Local Path)
For Production (Git Repository)
Push your identity to a Git repo:Monorepo Layout
Multiple identities can share a single repo:https://github.com/org/my-identities#researcher, #analyst, etc.
Template Variables
Workspace files support{{VARIABLE}} substitution.
How It Works
- Declare variables in
templateVarsinidentity.yaml - Use
{{VARIABLE_NAME}}in any workspace file - During
clawup init, any template variables not auto-filled from owner info must be added totemplateVarsinclawup.yaml - Values are substituted before files are injected into the agent
Standard Variables
| Variable | Description |
|---|---|
OWNER_NAME | Name of the agent’s owner |
TIMEZONE | Owner’s timezone (e.g., America/New_York) |
WORKING_HOURS | Working hours (e.g., 9am-6pm) |
USER_NOTES | Free-form notes for the agent |
Custom Variables
You can define any variable name:Check open issues in {{LINEAR_TEAM}}.
Declaring Additional Secrets
If your identity needs secrets beyond what itsplugins and deps imply (e.g., a Notion API key, a Sentry DSN), declare them in requiredSecrets:
SCREAMING_SNAKE_CASE and prefixed with the agent’s role for the env var name. Add the values to your .env file — clawup deploy validates that all required secrets are present and reports any that are missing.
This is additive — plugin/dep-implied secrets are always included. If a key appears in both requiredSecrets and is already implied by a plugin, it won’t be duplicated.
See Environment Variables for full details on secret resolution.
Tips
- Start with
army-create. Runnpx army-createto scaffold a new identity interactively (GitHub · npm). Or copyexamples/identity/for a single agent, orexamples/multi-agent/for a full PM + Engineer + Tester fleet. - Keep SOUL.md focused. 30-50 lines is plenty. Agents work better with clear, concise personality guidance.
- Test locally first. Use a local path identity during development, switch to Git URL for production.
- One skill per workflow. Each skill should handle one complete workflow. If a skill is doing too much, split it.
- Use
user-invocable: falsefor skills that are triggered by the system (queue handlers, routers) rather than by users.