Safe-by-default since PR #2236. Every mutation (
create, edit, patch, delete, write_file, remove_file) is now staged for human approval by default. The agent receives {"status": "pending", "id": "skl-…"} instead of writing to disk. Pass propose=False to restore direct-write behaviour in trusted/local contexts.Quick Start
1
Agent proposes a skill (default behaviour)
2
Human reviews and approves
3
Direct write (trusted/local contexts only)
4
Archive and recover skills
Approval Gate (safe-by-default)
Every mutation is staged by default so a human can review it before it becomes a live skill. The agent sees apending response; you approve or reject via the SkillManager API or the skill_manage tool.
When to use propose=False
How It Works
The skill management system provides six mutation actions, three approval actions, and four lifecycle actions:Configuration
Constructor & environment
Precedence: explicit
propose= arg > SkillManager(write_approval=...) > SKILL_WRITE_APPROVAL env var > default True
Skill management actions
Python API Reference
Response shapes
Staged (default) —propose=True:
propose=False:
Mutation methods
Approval state machine
Approval requires a valid This prevents a stray or partially-written pending directory from clobbering an existing active skill. Malformed
SKILL.md (since PraisonAI PR #2467). approve() checks that the pending directory contains SKILL.md before moving it into the active skills directory. A pending entry without SKILL.md returns:.proposal.json metadata no longer blocks approval — it is treated as a legacy create record as long as SKILL.md is present.SkillMutatorProtocol aliases
SkillManager conforms to SkillMutatorProtocol. Short-form aliases are available alongside the _skill methods:
Pending Store & Audit Log
Both artefacts always live in the user-owned skills directory (~/.praisonai/skills/, honouring PRAISONAI_HOME), regardless of cwd — so a proposal staged from one project is discoverable when the approver runs from another:
Pending record shape:
approve only consumes the pending record and audits “approved” if the apply succeeds. On failure, the record is kept and the audit logs “approval_failed” so you can retry.Visibility rules
list_pending() only surfaces a pending directory when it carries a real SKILL.md. Stray temp directories or directories that contain nothing but a malformed .proposal.json are silently excluded so they cannot be advertised as approvable.
Storage Location
SkillManager uses different rules for where it writes mutations versus where it discovers existing skills for read.
Write-path change (PR #3040):
create_skill now prefers the project-scoped ./.praisonai/skills/ when that directory exists in the current working directory, falling back to user home otherwise. Previously it always wrote to the user-owned get_skills_dir().Write path (mutations)
create_skill, edit_skill, patch_skill, write_skill_file, and their aliases resolve their destination via _skills_base_dir():
- Project (preferred):
./.praisonai/skills/— used when that directory already exists in the current working directory. - User home (fallback):
~/.praisonai/skills/— used otherwise. HonoursPRAISONAI_HOME.
/etc/praison/skills — those apply to discovery only.
Where did the file land? On a successful direct create, the SDK emits an INFO log:Enable it with
logging.basicConfig(level=logging.INFO). This is the definitive signal for whether the write went to the project or the user-home fallback.Approval writes back to the origin project
Staging a create withpropose=True pins the resolved destination into the pending record (payload.base_dir). Approving that record later — even from a completely different working directory — writes the SKILL.md back to the project the proposal originated in.
Discovery path (read)
Discovery (get_default_skill_dirs()) walks a broader list — unchanged, and applies to read only:
- Project:
./.praisonai/skills/— and./.claude/skills/for compatibility - Ancestor walk: any
.praisonai/skillsor.claude/skillsin parent directories - User:
~/.praisonai/skills/(or$PRAISONAI_HOME/skills/) - System (Unix):
/etc/praison/skills/
<first_skill_dir>/../skills_archive/. If a name already exists in the archive, a UTC timestamp suffix is appended (e.g. weekly-summary.20240624153012).
Security Guards
Common Patterns
Complete approval flow
Local dev — disable staging
Skill evolution with approval
Safe edit with rollback
Using the skill_manage tool actions directly
Skill Bundles
Group related skills into named, reusable sets withpraisonai skills bundle list and praisonai skills bundle show <name>. Select a whole bundle from an agent with skills=["@backend-dev"]. See Skill Bundles for the full guide.
Troubleshooting
Best Practices
Keep propose=True for unattended gateway/bot deployments
Keep propose=True for unattended gateway/bot deployments
In any unattended context — Slack bots, webhooks, scheduled agents — leave
propose=True (the default). This ensures no skill mutation reaches disk without a human seeing it first. Set SKILL_WRITE_APPROVAL=0 only on machines you control and trust.Use SKILL_WRITE_APPROVAL=0 only in trusted local CI/dev
Use SKILL_WRITE_APPROVAL=0 only in trusted local CI/dev
Direct writes are convenient for rapid iteration in local development or a controlled CI pipeline where you own the environment. Never disable staging for agents exposed to external users or production traffic.
Approve by ID, not by name
Approve by ID, not by name
approve("skl-a1b2c3d4") is exact — it targets one specific proposal. approve("weekly-summary") uses a most-recent-wins fallback and can silently target the wrong proposal if multiple are pending for the same skill.Security-First Design
Security-First Design
All skill operations are workspace-contained and use atomic writes via temp files. Never bypass name validation or path checks. Skills inherit workspace security automatically.
Error Handling
Error Handling
All skill operations return detailed JSON results with success flags and error messages. Always check
result["success"] before proceeding. On approval failure, the pending record is kept — check mgr.list_pending() and retry.Don't pre-create empty pending directories
Don't pre-create empty pending directories
A pending directory is only approvable when it contains
SKILL.md. If you stage skills outside the skill_manage tool (e.g. via a script that writes to <skills_dir>/pending/<name>/), write SKILL.md first — approval will fail until it is present, and list_pending() will not show the entry.Related
Skill Lifecycle
Provenance, telemetry, archive/restore, and rollback for agent-created skills
Agent Skills
Load and configure SKILL.md skills on agents
Workspace
How workspace containment secures skill operations
Skill Capability Gates
Capability requirements and enforcement for skills
Self-Improving Agents
Auto-trigger skill_manage after each task with self_improve=True

