self_improve=True on an agent and after every task it asks itself “did I just learn something reusable?” — if yes, it writes or patches a skill for next time. Use self_improve="background" to reply first and run the review off the hot path.
Before you run any example:
- 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.
Supported invocation paths.
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).Quick Start
1
Simple Usage
NO_SKILL.2
With Configuration
Require at least three tool calls before a review fires:
3
Background Mode (no added latency)
Reply first, run the review turn off the hot path — ideal for latency-sensitive gateway and bot agents:
4
Chat and Async Chat
The same The review pass is scheduled after every chat turn that used ≥1 tool — inline for
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".How It Works
The task phase requires
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 only
skill_manageavailable - The agent calls
skill_manageto create/patch a skill, 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=...)
An unrecognised string (e.g. a typo like
"backround") disables self-improvement and logs a warning rather than silently enabling a review on every reply.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
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. - 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.
Background mode guarantees
- 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
The model judged that nothing durable emerged, so it replied
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
Self-improve only reviews when the task used at least one tool — the guarded review skips tool-less tasks. Confirm the agent has
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()?
On Confirm the fix with a one-line reproducer:If the review still doesn’t run on 1.6.151+, check the other accordions — the most common causes are (a) no
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.Best Practices
Start with True, then tune
Start with True, then tune
The default policy is conservative (≥1 tool call). Only switch to a custom
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
Skills written by the review land in the project’s
./.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
Any object with
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
If your agent lives inside a chatbot, gateway, or bot process where users notice reply latency, pass
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.Related
Skill Manage
The underlying tool the review uses to create and patch skills
Skills
What skills are and how agents use them
Hooks
Where the review trigger is wired — the after-agent funnel
Self Reflection
Improves answer quality within a task

