You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two recent SDK fixes on MervinPraison/PraisonAI change user-visible behaviour of agent.close() / agent.aclose(), the tool circuit breaker, MCP transport shutdown, and the LLM-instance resolution used by guardrails and token tracking. The existing docs either miss the new behaviour or actively contradict it (circuit-breaker retrieval by name no longer returns the runtime breaker).
Per AGENTS.md §1.8, all NEW pages and updates MUST go in docs/features/. Do not modify anything under docs/concepts/, docs/js/, or docs/rust/. Concept-page suggestions listed in section C below are for human review only.
Summary of behaviour changes
#
Change
User impact
SDK file (praisonai-package/)
1
MCP.shutdown() now falls back to close() for HTTPStreamMCPClient / WebSocketMCPClient, which only expose close() / aclose() (not shutdown()). Also fixes Agent.aclose() fallback.
HTTP-stream and WebSocket MCP transports no longer leak subprocesses/threads on shutdown; context-manager exit and mcp.shutdown() are now reliable across every transport.
src/praisonai-agents/praisonaiagents/mcp/mcp.py
2
Agent.close() and Agent.aclose() now walk self.tools for MCP-like objects (anything with shutdown() / aclose()) instead of the always-empty self._mcp_clients dict.
MCP clients passed at construction time via Agent(tools=[MCP(...)]) are now deterministically shut down when the agent is closed. Previously they leaked.
Circuit-breaker registry key changed from f"tool_{function_name}" to f"tool_{id(self)}_{function_name}" — scoped to the Agent instance.
One agent's failing tool no longer trips the breaker for another agent's same-named tool. But: any existing code that calls get_circuit_breaker("tool_my_tool") will now retrieve a different breaker from the one actually protecting runtime calls.
Agent.close() / Agent.aclose() now call _cleanup_circuit_breakers() to remove that agent's instance-scoped breakers from the process-global registry.
The registry stays bounded across create/close cycles, and a reused CPython object id cannot inherit a stale OPEN breaker from a previously-collected agent.
Guardrail and token-tracking paths now prefer getattr(self, 'llm_instance', None) over getattr(self, 'llm', None). The llm attribute is always a truthy model-name string, so the old fallback order silently discarded configured api_key / base_url / client overrides and disabled set_current_agent / last_token_metrics wiring.
LLM-based string guardrails and PraisonAIAgents token metrics now use the configured LLM instance (with its overrides), not the bare model-name string. set_current_agent and last_token_metrics are re-connected on the multi-agent path.
Covers items #2, #4 — the agent-level cleanup story for MCP tools and circuit breakers. Currently the only doc that even mentions agent.close() / agent.aclose() is docs/features/runtime-mcp.mdx, and it only covers the runtime-attached case.
Required structure (per AGENTS.md template):
Frontmatter: icon: "broom", title "Agent Lifecycle Cleanup", sidebar "Agent Cleanup".
Step 1 — Simple: agent-centric example with Agent(tools=[MCP("uvx mcp-server-time")]) followed by agent.close(); note that subprocesses/streams shut down deterministically.
Step 2 — Async: same example using async with on a helper, or explicit await agent.aclose().
How It Works sequenceDiagram: user → agent → (memory close, LLM close, MCP tool shutdown(), runtime-MCP _shutdown_runtime_mcp_servers(), circuit-breaker registry prune) → clean exit.
What gets cleaned up (table) — mirror exactly what Agent.close() / Agent.aclose() do (source: praisonaiagents/agent/agent.py:6121-6215 and :6217-6281):
Resource
Sync path
Async path
Notes
llm_instance client
close() / bridged aclose()
aclose() if awaitable
Falls back to __openai_client.close() and self.llm._client.close() for legacy patterns.
Memory (_memory_instance / memory)
close_connections()
await memory.aclose() else close_connections()
MCP tools passed via tools=[MCP(...)]
t.shutdown() for each tool in self.tools
prefer await t.aclose(), else t.shutdown()
New in #3131. Mirrors remove_mcp_server().
Runtime-attached MCPs
_shutdown_runtime_mcp_servers()
same
Existing behaviour, now cross-linked.
Circuit breakers
_cleanup_circuit_breakers()
same
New in #3131. Removes every tool_{id(self)}_* entry from the global registry.
Background tasks
task.cancel()
task.cancel() + await task
Thread-pool executor
shutdown(wait=False, cancel_futures=True)
same via run_in_executor
Idempotency note: close() / aclose() set _closed = True and become no-ops on subsequent calls.
Best practices <AccordionGroup>:
Prefer with PraisonAIAgents(...) as workflow: — team-level context manager fans out to each agent's close() (link to docs/features/resource-lifecycle.mdx).
For a single agent, wrap in try/finally or write a small helper that calls agent.close().
Do not rely on __del__ alone — cleanup is best-effort under GC and the async client cannot be awaited.
Note that cleanup failures are logged as warnings and never raise, so they never mask the original error.
Related <CardGroup>:
docs/features/runtime-mcp.mdx — attaching / detaching MCPs at runtime.
The page's current get_circuit_breaker("tool_my_tool") examples will silently return a fresh, disconnected breaker after the fix, because the runtime key is now f"tool_{id(agent)}_{function_name}". Update as follows:
Add a callout near the top (<Warning>): breaker keys are now scoped to the Agent instance (tool_{id(agent)}_{function_name}). Retrieving a breaker by tool name alone no longer returns the runtime instance. Point readers at the new observability pattern below and at the new agent-lifecycle-cleanup.mdx for the auto-prune behaviour.
Line 108 (get_circuit_breaker("tool_my_tool", ...)), line 232 (get_circuit_breaker("tool_my_tool")), lines 254 & 261 (get_circuit_breaker("tool_external_api", ...) / get_circuit_breaker("tool_internal_db", ...)), and line 276 (get_circuit_breaker("tool_my_tool")):
Replace with the new key format: get_circuit_breaker(f"tool_{id(agent)}_my_tool").
In the "Custom Config Per Tool" tab, restructure the example so the config is registered before the agent runs the tool for the first time (the breaker is lazily created on first call using the config passed to get_circuit_breaker — see agent/tool_execution.py:1859-1880 for exact semantics). If pre-registration is not viable with the new keying, replace the tab with guidance to fork the tool with a wrapper that owns its own breaker.
Update the Observability tab (line 225 onward) — show how to enumerate this agent's breakers:
Add a new subsection "Lifecycle" explaining that agent.close() / agent.aclose() removes every tool_{id(agent)}_* entry from the registry, keeping it bounded and preventing a reused id from inheriting a stale OPEN breaker. Cross-link to docs/features/agent-lifecycle-cleanup.mdx.
Update the Best Practices accordion "Reset between test runs" to note that per-agent breakers are also auto-pruned by agent.close(), so reset_all_circuit_breakers() remains the sledgehammer for global tests but per-request isolation is now free when the agent is closed.
Source lines to verify against: praisonaiagents/agent/tool_execution.py:1859-1880 and praisonaiagents/agent/agent.py:4705-4725, 6121-6281.
B2. docs/features/mcp-lifecycle.mdx
Update the "Connection Types" section (line 211) so the four-transport list (stdio / SSE / HTTP Stream / WebSocket) explicitly states that HTTP-stream and WebSocket now close via the close() fallback inside MCP.shutdown() — previously these two transports leaked on shutdown.
Extend "Lifecycle Methods → shutdown()" (line 193) with a short table:
Transport
Client method actually invoked
Stdio
subprocess terminate + stream close
SSE
HTTP stream close
HTTP Stream
close() (fallback added in #3131)
WebSocket
close() (fallback added in #3131)
Add a Related card pointing to the new docs/features/agent-lifecycle-cleanup.mdx.
Source lines: praisonaiagents/mcp/mcp.py:1085-1112 (specifically the new hasattr(..., 'close') fallbacks for http_stream_client and websocket_client).
B3. docs/features/runtime-mcp.mdx
Update the "Cleanup" section (line 135) to note that agent.close() / agent.aclose() now also shut down MCP objects passed at construction time via Agent(tools=[MCP(...)]) — not just runtime-attached servers. Add one sentence:
agent.close() and await agent.aclose() also walk self.tools and call shutdown() / aclose() on any construction-time MCP objects, so you get the same clean-shutdown guarantee whether you attach an MCP at build time or add one at runtime.
Add a Related card pointing to the new docs/features/agent-lifecycle-cleanup.mdx.
Source lines: praisonaiagents/agent/agent.py:6168-6180 (sync) and :6228-6240 (async).
B4. docs/features/mcp-client-protocol.mdx
Add a paragraph in "Protocol Methods" (around line 117) explaining the current dispatch order used by MCP.shutdown(): it prefers shutdown(), falls back to close(), then to aclose() if awaitable. Custom MCPClientProtocol implementations that expose only close() (as many httpx-style clients do) are now fully supported at teardown.
Cross-link to docs/features/mcp-lifecycle.mdx#shutdown and to the new agent-lifecycle-cleanup.mdx.
Add a short "LLM-based guardrails" callout (<Note>): when guardrail is a string, PraisonAI now resolves the underlying LLM by preferring agent.llm_instance over agent.llm. This ensures the guardrail LLM inherits api_key, base_url, and any custom client you passed to the agent — previously the string form silently discarded these overrides.
Do not touch docs/concepts/guardrails.mdx (concept-page edits need human approval — flag in section C).
Source lines: praisonaiagents/agent/agent.py:5507-5514 (the new llm_instance-first fallback in _setup_llm_guardrail).
B6. docs/features/token-tracking.mdx (if the page exists — otherwise skip; do not create a new page in this issue)
Add a note that in multi-agent teams the executor's LLM instance (executor_agent.llm_instance) is now the one wired into set_current_agent() / last_token_metrics, so per-agent token accounting is accurate again for agents constructed with a real LLM object rather than a bare model-name string.
Source lines: praisonaiagents/agents/agents.py:357-368 (the reordered getattr(..., 'llm_instance', None) or getattr(..., 'llm', None)).
C. Concept-page suggestions (HUMAN APPROVAL ONLY — do NOT auto-edit)
Flag these for maintainer review; the AI agent must not modify these files under docs/concepts/:
docs/concepts/mcp.mdx (293 lines) — the "Connection Types" table (line 84) should note that HTTP Stream / WebSocket cleanup is now uniform with stdio and SSE.
docs/concepts/guardrails.mdx (586 lines) — clarify that string guardrails now inherit the agent's configured llm_instance (not the bare llm model-name string), and cross-reference the on_error hook if applicable.
docs/concepts/agents.mdx — add a brief "Lifecycle" subsection linking to the new docs/features/agent-lifecycle-cleanup.mdx.
Reference: SDK source files to read
The downstream agent MUST read these files before writing/updating each page (per AGENTS.md §1.2 SDK-First Cycle). Paths are relative to MervinPraison/PraisonAI:
_get_global_registry(), list_services(), remove() — for the new observability example in B1.
Per AGENTS.md §1.4, the SDK paths in the docs repo are under repo root praisonaiagents/ (synced daily by update_repos.sh). Verify each cited line against the mirrored copy in PraisonAIDocs/praisonaiagents/ before writing.
Multi-SDK parity: The circuit-breaker key change and the MCP-tool cleanup are Python-only. TypeScript (src/praisonai-ts/) and Rust (src/praisonai-rust/) implementations should be checked; if they lack an equivalent, do not add TS/Rust pages — the auto-generated parity tables (docs/js/DOCS_PARITY.md, docs/rust/DOCS_PARITY.md) will surface the gap.
Acceptance checklist for the doc PR
New page docs/features/agent-lifecycle-cleanup.mdx created with full Mintlify frontmatter, hero Mermaid diagram (AGENTS.md colour scheme), <Steps> Quick Start, <AccordionGroup> best practices, <CardGroup> related links.
Quick Start is agent-centric and copy-paste runnable: minimal imports (from praisonaiagents import Agent, MCP), no placeholder values.
docs/features/tool-circuit-breaker.mdx updated so every get_circuit_breaker("tool_...") example uses the new f"tool_{id(agent)}_..." key format (or is replaced with the new observability pattern), plus the new <Warning> callout and Lifecycle subsection.
docs/features/token-tracking.mdx update B6 applied only if the page already exists — do not create a new page for this in this pass.
docs.json updated to register docs/features/agent-lifecycle-cleanup.mdx under the Features group (never under Concepts), and JSON validity re-verified.
No edits inside docs/concepts/, docs/js/, or docs/rust/.
All code examples verified against the SDK source lines listed in the "Reference" section above.
Every code block runs without modification (imports included, no "your-key-here" placeholders).
Mermaid diagrams use the standard colour scheme and white text.
If parity trackers are affected, run python3 src/praisonai/scripts/generate_docs_parity.py --copy-docs before pushing.
Branch instructions for the downstream agent
Per the task instructions for this routine:
Develop on branch claude/admiring-euler-jku6yc in MervinPraison/PraisonAIDocs.
Push with git push -u origin claude/admiring-euler-jku6yc and open a draft PR referencing this issue.
Context
Two recent SDK fixes on
MervinPraison/PraisonAIchange user-visible behaviour ofagent.close()/agent.aclose(), the tool circuit breaker, MCP transport shutdown, and the LLM-instance resolution used by guardrails and token tracking. The existing docs either miss the new behaviour or actively contradict it (circuit-breaker retrieval by name no longer returns the runtime breaker).Source commits on
MervinPraison/PraisonAI:48d51f1—fix: MCP client leaks, cross-agent circuit-breaker bleed, dead llm getattr fallback (fixes #3130)021d193—fix: async MCP transport cleanup + circuit-breaker registry leakRelated upstream issue:
MervinPraison/PraisonAI#3130.Important
Per
AGENTS.md§1.8, all NEW pages and updates MUST go indocs/features/. Do not modify anything underdocs/concepts/,docs/js/, ordocs/rust/. Concept-page suggestions listed in section C below are for human review only.Summary of behaviour changes
praisonai-package/)MCP.shutdown()now falls back toclose()forHTTPStreamMCPClient/WebSocketMCPClient, which only exposeclose()/aclose()(notshutdown()). Also fixesAgent.aclose()fallback.mcp.shutdown()are now reliable across every transport.src/praisonai-agents/praisonaiagents/mcp/mcp.pyAgent.close()andAgent.aclose()now walkself.toolsfor MCP-like objects (anything withshutdown()/aclose()) instead of the always-emptyself._mcp_clientsdict.Agent(tools=[MCP(...)])are now deterministically shut down when the agent is closed. Previously they leaked.src/praisonai-agents/praisonaiagents/agent/agent.pyf"tool_{function_name}"tof"tool_{id(self)}_{function_name}"— scoped to the Agent instance.get_circuit_breaker("tool_my_tool")will now retrieve a different breaker from the one actually protecting runtime calls.src/praisonai-agents/praisonaiagents/agent/tool_execution.pyAgent.close()/Agent.aclose()now call_cleanup_circuit_breakers()to remove that agent's instance-scoped breakers from the process-global registry.OPENbreaker from a previously-collected agent.src/praisonai-agents/praisonaiagents/agent/agent.pygetattr(self, 'llm_instance', None)overgetattr(self, 'llm', None). Thellmattribute is always a truthy model-name string, so the old fallback order silently discarded configuredapi_key/base_url/clientoverrides and disabledset_current_agent/last_token_metricswiring.PraisonAIAgentstoken metrics now use the configured LLM instance (with its overrides), not the bare model-name string.set_current_agentandlast_token_metricsare re-connected on the multi-agent path.src/praisonai-agents/praisonaiagents/agent/agent.py,src/praisonai-agents/praisonaiagents/agents/agents.pyDocumentation work needed
A. NEW page — place in
docs/features/A1.
docs/features/agent-lifecycle-cleanup.mdx(NEW)Covers items #2, #4 — the agent-level cleanup story for MCP tools and circuit breakers. Currently the only doc that even mentions
agent.close()/agent.aclose()isdocs/features/runtime-mcp.mdx, and it only covers the runtime-attached case.Required structure (per
AGENTS.mdtemplate):Frontmatter:
icon: "broom", title"Agent Lifecycle Cleanup", sidebar"Agent Cleanup".Hero Mermaid diagram: agent →
close()→ { LLM client, memory, MCP tools, runtime MCPs, circuit breakers, background tasks, executors } → clean exit. Use the AGENTS.md colour scheme (#8B0000agent,#189AB4process,#10B981success).Quick Start
<Steps>:Agent(tools=[MCP("uvx mcp-server-time")])followed byagent.close(); note that subprocesses/streams shut down deterministically.async withon a helper, or explicitawait agent.aclose().How It Works
sequenceDiagram: user → agent → (memory close, LLM close, MCP toolshutdown(), runtime-MCP_shutdown_runtime_mcp_servers(), circuit-breaker registry prune) → clean exit.What gets cleaned up (table) — mirror exactly what
Agent.close()/Agent.aclose()do (source:praisonaiagents/agent/agent.py:6121-6215and:6217-6281):llm_instanceclientclose()/ bridgedaclose()aclose()if awaitable__openai_client.close()andself.llm._client.close()for legacy patterns._memory_instance/memory)close_connections()await memory.aclose()elseclose_connections()tools=[MCP(...)]t.shutdown()for each tool inself.toolsawait t.aclose(), elset.shutdown()remove_mcp_server()._shutdown_runtime_mcp_servers()_cleanup_circuit_breakers()tool_{id(self)}_*entry from the global registry.task.cancel()task.cancel()+await taskshutdown(wait=False, cancel_futures=True)run_in_executorIdempotency note:
close()/aclose()set_closed = Trueand become no-ops on subsequent calls.Best practices
<AccordionGroup>:with PraisonAIAgents(...) as workflow:— team-level context manager fans out to each agent'sclose()(link todocs/features/resource-lifecycle.mdx).try/finallyor write a small helper that callsagent.close().__del__alone — cleanup is best-effort under GC and the async client cannot be awaited.Related
<CardGroup>:docs/features/runtime-mcp.mdx— attaching / detaching MCPs at runtime.docs/features/mcp-lifecycle.mdx— per-MCPcontext manager & manualshutdown().docs/features/resource-lifecycle.mdx— team-levelwith PraisonAIAgents(...).docs/features/tool-circuit-breaker.mdx— how per-agent breakers work.B. Updates to existing FEATURE pages (AI agents may edit)
B1.
docs/features/tool-circuit-breaker.mdx— breaking-change fix requiredThe page's current
get_circuit_breaker("tool_my_tool")examples will silently return a fresh, disconnected breaker after the fix, because the runtime key is nowf"tool_{id(agent)}_{function_name}". Update as follows:<Warning>): breaker keys are now scoped to the Agent instance (tool_{id(agent)}_{function_name}). Retrieving a breaker by tool name alone no longer returns the runtime instance. Point readers at the new observability pattern below and at the newagent-lifecycle-cleanup.mdxfor the auto-prune behaviour.get_circuit_breaker("tool_my_tool", ...)), line 232 (get_circuit_breaker("tool_my_tool")), lines 254 & 261 (get_circuit_breaker("tool_external_api", ...)/get_circuit_breaker("tool_internal_db", ...)), and line 276 (get_circuit_breaker("tool_my_tool")):get_circuit_breaker(f"tool_{id(agent)}_my_tool").get_circuit_breaker— seeagent/tool_execution.py:1859-1880for exact semantics). If pre-registration is not viable with the new keying, replace the tab with guidance to fork the tool with a wrapper that owns its own breaker.agent.close()/agent.aclose()removes everytool_{id(agent)}_*entry from the registry, keeping it bounded and preventing a reused id from inheriting a staleOPENbreaker. Cross-link todocs/features/agent-lifecycle-cleanup.mdx.agent.close(), soreset_all_circuit_breakers()remains the sledgehammer for global tests but per-request isolation is now free when the agent is closed.Source lines to verify against:
praisonaiagents/agent/tool_execution.py:1859-1880andpraisonaiagents/agent/agent.py:4705-4725, 6121-6281.B2.
docs/features/mcp-lifecycle.mdxUpdate the "Connection Types" section (line 211) so the four-transport list (stdio / SSE / HTTP Stream / WebSocket) explicitly states that HTTP-stream and WebSocket now close via the
close()fallback insideMCP.shutdown()— previously these two transports leaked on shutdown.Extend "Lifecycle Methods →
shutdown()" (line 193) with a short table:close()(fallback added in #3131)close()(fallback added in #3131)Add a Related card pointing to the new
docs/features/agent-lifecycle-cleanup.mdx.Source lines:
praisonaiagents/mcp/mcp.py:1085-1112(specifically the newhasattr(..., 'close')fallbacks forhttp_stream_clientandwebsocket_client).B3.
docs/features/runtime-mcp.mdxUpdate the "Cleanup" section (line 135) to note that
agent.close()/agent.aclose()now also shut down MCP objects passed at construction time viaAgent(tools=[MCP(...)])— not just runtime-attached servers. Add one sentence:Add a Related card pointing to the new
docs/features/agent-lifecycle-cleanup.mdx.Source lines:
praisonaiagents/agent/agent.py:6168-6180(sync) and:6228-6240(async).B4.
docs/features/mcp-client-protocol.mdxMCP.shutdown(): it prefersshutdown(), falls back toclose(), then toaclose()if awaitable. CustomMCPClientProtocolimplementations that expose onlyclose()(as manyhttpx-style clients do) are now fully supported at teardown.docs/features/mcp-lifecycle.mdx#shutdownand to the newagent-lifecycle-cleanup.mdx.Source lines:
praisonaiagents/mcp/mcp.py:1080-1112.B5.
docs/features/guardrails.mdx(feature page)<Note>): whenguardrailis a string, PraisonAI now resolves the underlying LLM by preferringagent.llm_instanceoveragent.llm. This ensures the guardrail LLM inheritsapi_key,base_url, and any customclientyou passed to the agent — previously the string form silently discarded these overrides.docs/concepts/guardrails.mdx(concept-page edits need human approval — flag in section C).Source lines:
praisonaiagents/agent/agent.py:5507-5514(the newllm_instance-first fallback in_setup_llm_guardrail).B6.
docs/features/token-tracking.mdx(if the page exists — otherwise skip; do not create a new page in this issue)executor_agent.llm_instance) is now the one wired intoset_current_agent()/last_token_metrics, so per-agent token accounting is accurate again for agents constructed with a real LLM object rather than a bare model-name string.Source lines:
praisonaiagents/agents/agents.py:357-368(the reorderedgetattr(..., 'llm_instance', None) or getattr(..., 'llm', None)).C. Concept-page suggestions (HUMAN APPROVAL ONLY — do NOT auto-edit)
Flag these for maintainer review; the AI agent must not modify these files under
docs/concepts/:docs/concepts/mcp.mdx(293 lines) — the "Connection Types" table (line 84) should note that HTTP Stream / WebSocket cleanup is now uniform with stdio and SSE.docs/concepts/guardrails.mdx(586 lines) — clarify that string guardrails now inherit the agent's configuredllm_instance(not the barellmmodel-name string), and cross-reference theon_errorhook if applicable.docs/concepts/agents.mdx— add a brief "Lifecycle" subsection linking to the newdocs/features/agent-lifecycle-cleanup.mdx.Reference: SDK source files to read
The downstream agent MUST read these files before writing/updating each page (per
AGENTS.md§1.2 SDK-First Cycle). Paths are relative toMervinPraison/PraisonAI:src/praisonai-agents/praisonaiagents/agent/agent.py_cleanup_circuit_breakers()— lines 4705-4725_setup_llm_guardrail()LLM resolution — lines 5507-5514close()— lines 6121-6215 (memory, LLM, MCP tools, runtime MCPs, circuit breakers, executor)aclose()— lines 6217-6281src/praisonai-agents/praisonaiagents/agent/tool_execution.pyf"tool_{id(self)}_{function_name}")src/praisonai-agents/praisonaiagents/agents/agents.py_build_execution_context()— lines 355-368 (llm_instance-first resolution for token tracking)src/praisonai-agents/praisonaiagents/mcp/mcp.pyMCP.shutdown()HTTP-stream / WebSocket fallbacks — lines 1080-1112src/praisonai-agents/praisonaiagents/tools/circuit_breaker.py_get_global_registry(),list_services(),remove()— for the new observability example in B1.Per
AGENTS.md§1.4, the SDK paths in the docs repo are under repo rootpraisonaiagents/(synced daily byupdate_repos.sh). Verify each cited line against the mirrored copy inPraisonAIDocs/praisonaiagents/before writing.Multi-SDK parity: The circuit-breaker key change and the MCP-tool cleanup are Python-only. TypeScript (
src/praisonai-ts/) and Rust (src/praisonai-rust/) implementations should be checked; if they lack an equivalent, do not add TS/Rust pages — the auto-generated parity tables (docs/js/DOCS_PARITY.md,docs/rust/DOCS_PARITY.md) will surface the gap.Acceptance checklist for the doc PR
docs/features/agent-lifecycle-cleanup.mdxcreated with full Mintlify frontmatter, hero Mermaid diagram (AGENTS.md colour scheme),<Steps>Quick Start,<AccordionGroup>best practices,<CardGroup>related links.from praisonaiagents import Agent, MCP), no placeholder values.docs/features/tool-circuit-breaker.mdxupdated so everyget_circuit_breaker("tool_...")example uses the newf"tool_{id(agent)}_..."key format (or is replaced with the new observability pattern), plus the new<Warning>callout andLifecyclesubsection.docs/features/mcp-lifecycle.mdxupdates B2 applied (Connection Types note +shutdown()transport table).docs/features/runtime-mcp.mdxupdate B3 applied (Cleanup section extended, Related card added).docs/features/mcp-client-protocol.mdxupdate B4 applied (dispatch-order paragraph + cross-links).docs/features/guardrails.mdxupdate B5 applied.docs/features/token-tracking.mdxupdate B6 applied only if the page already exists — do not create a new page for this in this pass.docs.jsonupdated to registerdocs/features/agent-lifecycle-cleanup.mdxunder the Features group (never underConcepts), and JSON validity re-verified.docs/concepts/,docs/js/, ordocs/rust/."your-key-here"placeholders).python3 src/praisonai/scripts/generate_docs_parity.py --copy-docsbefore pushing.Branch instructions for the downstream agent
Per the task instructions for this routine:
claude/admiring-euler-jku6ycinMervinPraison/PraisonAIDocs.git push -u origin claude/admiring-euler-jku6ycand open a draft PR referencing this issue.cc @MervinPraison