self_improve=True on an agent and after every task it asks itself “did I just learn something reusable, or a durable fact worth remembering?” — if yes, it writes/patches a skill and/or persists a memory for next time. Use self_improve="background" to reply first and run the review off the hot path.
- Install the SDK:
pip install praisonaiagents - Set your key:
export OPENAI_API_KEY=sk-... - Every learning example needs
tools=— the review gate only fires after a real tool call. SKILL_WRITE_APPROVALdefaults on, so new skills are staged for approval. SetSKILL_WRITE_APPROVAL=0for direct local writes.- Windows: run with
python script.py.
self_improve= must name a valid preset (inline, blocking, sync, background, …). A typo raises ValueError at construction time with a “Did you mean …?” suggestion — see Fail-Loud Defaults. Matching is case-insensitive, whitespace-tolerant, and treats -/_ interchangeably.self_improve triggers the review after any of these end-of-turn moments — pick whichever fits your app:agent.start(prompt)— the task-execution path.agent.chat(prompt)— the conversational path (chatbots, REPLs).agent.achat(prompt)— the async conversational path (gateways, servers).- Any custom loop that ends by returning through the after-agent hook.
execute_tool_async or async tool functions) are tracked identically to sync ones. Requires praisonaiagents >= 1.6.151 — earlier versions silently skipped the review on chat / achat paths (see Troubleshooting below).store_memory is only added to the review toolset when the agent has memory=True. Skill-only agents are unchanged.Quick Start
Simple Usage
NO_SKILL.With Configuration
Background Mode (no added latency)
Chat and Async Chat
self_improve flag works with chat() / achat() — the review fires after any turn that used at least one tool.self_improve=True, off the hot path for self_improve="background".Background + Memory (grow skills and user model)
memory=True, the same guarded review pass can also persist a durable fact via store_memory — closing the learning loop for memory, not just skills.How It Works
tools= on the Agent. Without a tool call, the default review gate exits early and no skill is written.agent.start(), agent.chat(), or agent.achat(), and whether the tool ran sync or async — if self_improve is enabled:
- The policy checks
should_review(trajectory)— by default, only when ≥1 tool was called - The agent runs one extra turn with a restricted toolset —
skill_managealways, plusstore_memorywhen the agent hasmemory=True - The agent calls
skill_manageto create/patch a skill, and/orstore_memoryto persist a durable fact, or repliesNO_SKILL - The internal review exchange is trimmed back out of
chat_history
Execution Modes
self_improve accepts strings that pick when the review runs relative to the reply.
- Inline (
True,"inline","blocking","sync") — the review turn runs before the reply returns. Simplest; adds one extra LLM round-trip to reply latency. - Background (
"background","async") — the reply returns first, then the review runs off the hot path on the sharedBackgroundJobManager. No added user-visible latency.
- Best-effort fallback — if the background runner is unreachable, the review runs inline rather than being dropped.
- Gateway clones —
clone_for_channel()preserves the background mode on per-channel gateway clones.
Configuration Options
Agent(self_improve=...)
"backround") disables self-improvement and logs a warning rather than silently enabling a review on every reply.memory=True, the guarded review turn additionally exposes store_memory so the same pass can persist a durable fact off the hot path. The set stays restricted — never the agent’s full toolset.
DefaultSkillReviewPolicy
SkillReviewProtocol (custom policy)
trajectory shape: {"prompt": str, "response": str, "tools_used": list[str]}.
Choosing What to Pass
Inline vs Background
Choose based on how latency-sensitive the reply is.Common Patterns
Agent that gets sharper over time
Persistent assistant that grows both skills and user model
Conservative policy (only review heavy sessions)
Fully custom policy
Guarantees
- Off by default — explicit opt-in via a single switch.
- Never runs with the full toolset — the review turn sees only
skill_manage(always) andstore_memory(only whenmemory=True). - Task echo is delimited as untrusted data — the review directive wraps the original task in
<original_task>…</original_task>and labels itUNTRUSTED DATA, so an injected instruction inside a user message cannot steerstore_memory/skill_manage. - Re-entrancy guarded — a review turn cannot trigger another review.
- Chat-history isolated — the review exchange is trimmed back out after the pass; chatbots and REPLs are unaffected.
- Best-effort — any failure is logged and swallowed; your main task response is never affected.
- Distinct from
reflection—reflectionretries for answer quality within a task;self_improvecaptures durable skills for next time. They are independent flags and compose cleanly.
- Reply first — the user-visible response returns before the review LLM turn starts.
- Serialized per agent — a background review holds a per-agent lock, so the next turn on the same agent waits its turn instead of racing chat-history state.
- Unique job id — every review gets a fresh id, so overlapping reviews never overwrite each other in the background job map.
- Falls back to inline — if the background job runner is unreachable, the review runs inline instead of being silently dropped.
- Same guardrails as inline — restricted-tool review turn, chat-history isolation, best-effort failure swallowing all still apply.
Troubleshooting
Ran self-improve and see noSKILL.md on disk? Work through these four causes in order.
1. The review returned NO_SKILL
1. The review returned NO_SKILL
NO_SKILL and wrote nothing. Enable INFO logging to see the review response:2. The create was staged for approval
2. The create was staged for approval
SKILL_WRITE_APPROVAL is on by default, so the review stages the skill instead of writing it. Check the pending store:~/.praisonai/skills/.pending_skills.json.3. The file went to user home, not the project cwd
3. The file went to user home, not the project cwd
./.praisonai/skills/ did not exist, so the write fell back to ~/.praisonai/skills/. Create the folder so the next run lands in the project:Skill created: after enabling INFO logging.4. The review pass never ran
4. The review pass never ran
tools= and that the task actually invoked one.5. Review not firing on agent.chat() / agent.achat()?
5. Review not firing on agent.chat() / agent.achat()?
praisonaiagents < 1.6.151, the chat and async-chat paths returned without wiring tools_used into the review hook, so the default policy always saw an empty tools list and skipped the review — silently, with no warning. Upgrade to fix:tools= on the Agent, (b) the task didn’t actually call a tool, or (c) SKILL_WRITE_APPROVAL staged the create rather than writing directly.6. Review wrote a skill but not a memory (or vice versa)
6. Review wrote a skill but not a memory (or vice versa)
store_memory is only in the review toolset when memory=True is set on the Agent. If you expected a memory write but see none, confirm the Agent has memory=True (or a MemoryConfig). See Memory for where the persisted fact lands per backend.Best Practices
Start with True, then tune
Start with True, then tune
min_tool_calls when you see review LLM cost you want to cut.Pair with named, persistent skill directories
Pair with named, persistent skill directories
./.praisonai/skills/ when that directory exists in the cwd, otherwise in ~/.praisonai/skills/. Discovery is broader (project → ancestors → user → system), but writes only use those two locations — they never walk ancestors. Run mkdir -p .praisonai/skills in the project you want captures to accumulate in.Don't confuse with reflection
Don't confuse with reflection
reflection improves this answer; self_improve captures a skill for next time. They compose cleanly — turn both on if you want both behaviors.Use the protocol for fully custom policies
Use the protocol for fully custom policies
should_review and review_prompt satisfies SkillReviewProtocol. Use this to gate on cost, time-of-day, session length, or any other signal.Use background mode for chatbots and gateways
Use background mode for chatbots and gateways
self_improve="background" instead of True. The review still runs after every task — it just doesn’t sit in front of the reply.Know how SKILL_WRITE_APPROVAL stages writes
Know how SKILL_WRITE_APPROVAL stages writes
SKILL_WRITE_APPROVAL is on by default, so a review that decides to save a skill stages it as a pending proposal instead of writing to disk. Approve it later, or set SKILL_WRITE_APPROVAL=0 for direct writes in trusted local tests.SkillManager.approve(id) from a different working directory — from ~, from a CI job, from another project — the approved skill is still written back to the original project’s .praisonai/skills/. You never lose the origin by approving elsewhere.Async tool calls made from achat or execute_tool_async are tracked identically to sync calls — the review fires whether the tool ran sync or async, and pending creates staged from an async turn behave the same as those staged from a sync turn.
