Skip to content

fix: knowledge scope enforcement, async persist offload, tool schema *args/**kwargs (fixes #3834) - #3835

Open
praisonai-triage-agent[bot] wants to merge 1 commit into
mainfrom
claude/issue-3834-20260810-0717
Open

fix: knowledge scope enforcement, async persist offload, tool schema *args/**kwargs (fixes #3834)#3835
praisonai-triage-agent[bot] wants to merge 1 commit into
mainfrom
claude/issue-3834-20260810-0717

Conversation

@praisonai-triage-agent

@praisonai-triage-agent praisonai-triage-agent Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Fixes #3834

Summary

Minimal, focused fixes for the three core-SDK gaps in the audit.

Gap 1 — Knowledge adapters diverged on tenant-scope (data-loss/leak)

  • Added a shared require_scope(...) helper in knowledge/protocols.py.
  • ChromaKnowledgeAdapter.delete_all and SQLiteKnowledgeAdapter.delete_all now call it, so an unscoped delete_all() raises ScopeRequiredError (matching the mem0 backend) instead of wiping the entire shared collection/table. Scoped deletes are unchanged.

Gap 2 — Async chat blocked the event loop on every turn

  • Added MemoryMixin._apersist_message, a thin async wrapper that offloads the file-locked _persist_message disk write via asyncio.to_thread (the same treatment _persist_compaction_checkpoint already got).
  • Swapped the 6 _persist_message call sites inside _achat_impl to await self._apersist_message(...).
  • The synchronous _chat_impl and the synchronous _start_stream generator correctly keep the sync call (the issue's line refs for the streaming sites actually fell in the sync generator).

Gap 3 — build_parameters_schema mis-marked *args/**kwargs as required

  • Skip VAR_POSITIONAL/VAR_KEYWORD params in build_parameters_schema, matching the filter build_tool_definition already applies. *args/**kwargs are no longer emitted as properties or in required.

Verification

  • @tool def f(query: str, **kwargs)required == ['query'], no kwargs property.
  • @tool def f(query: str, *args, flag=False)required == ['query'].
  • Unscoped delete_all() on SQLite and Chroma adapters raises ScopeRequiredError; scoped delete still removes only the matching rows.
  • _apersist_message is a coroutine offloading to a worker thread; all 6 async call sites confirmed inside _achat_impl.

Note: the sandbox blocked direct pytest invocation, so verification was done via targeted import/behaviour scripts.

Generated with Claude Code

Summary by CodeRabbit

  • Performance

    • Improved asynchronous chat handling by moving message persistence off the event loop, helping responses remain responsive.
  • Bug Fixes

    • Prevented unscoped knowledge-base deletion requests from removing entire collections or tables.
    • Preserved scoped deletion behavior using provided identifiers.
    • Excluded variadic parameters from generated tool schemas to produce more accurate definitions.

…rgs from tool schema (fixes #3834)

Gap 1: add shared require_scope() in knowledge/protocols.py and enforce it in
ChromaKnowledgeAdapter.delete_all and SQLiteKnowledgeAdapter.delete_all so an
unscoped delete_all raises ScopeRequiredError instead of wiping the whole
shared store, matching mem0's existing contract.

Gap 2: add MemoryMixin._apersist_message async wrapper that offloads
_persist_message to a worker thread, and await it at every _achat_impl call
site so file-locked disk I/O no longer blocks the event loop each turn (sync
_chat_impl and the sync _start_stream generator keep the sync call).

Gap 3: skip VAR_POSITIONAL/VAR_KEYWORD in build_parameters_schema so *args and
**kwargs are no longer emitted as required parameters, matching
build_tool_definition and preventing invalid schemas / tool-call TypeErrors.

Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
@MervinPraison

Copy link
Copy Markdown
Owner

@coderabbitai review

@MervinPraison

Copy link
Copy Markdown
Owner

/review

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@MervinPraison MervinPraison added pipeline/blocked:ci Blocked: CI not green on HEAD pipeline/blocked:manual-review Blocked: requires manual review pipeline/blocked:no-final Blocked: no FINAL @claude trigger yet pipeline/final-claude-pending Reviews done; waiting for FINAL @claude labels Aug 10, 2026
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Async chat persistence now uses worker-thread offloading. ChromaDB and SQLite deletion require tenant scope. Tool schemas exclude *args and **kwargs from properties and required parameters.

Changes

Async message persistence

Layer / File(s) Summary
Worker-thread message persistence
src/praisonai-agents/praisonaiagents/agent/memory_mixin.py, src/praisonai-agents/praisonaiagents/agent/chat_mixin.py
Adds _apersist_message with asyncio.to_thread and uses it across async response and reflection paths.

Scoped knowledge deletion

Layer / File(s) Summary
Scope validation contract
src/praisonai-agents/praisonaiagents/knowledge/protocols.py
Adds require_scope, which raises ScopeRequiredError when all scope identifiers are missing.
Scoped adapter deletion
src/praisonai-agents/praisonaiagents/knowledge/adapters/factories.py
ChromaDB and SQLite delete_all operations require scope and retain filtered deletion behavior.

Tool parameter schema

Layer / File(s) Summary
Variadic parameter filtering
src/praisonai-agents/praisonaiagents/tools/schema.py
Excludes variadic positional and keyword parameters from generated properties and required lists.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: mervinpraison

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements Chroma, SQLite, async persistence, and schema fixes, but it does not show scope validation for MongoDB and Mem0 as required by #3834. Add consistent require_scope enforcement to the MongoDB and Mem0 adapters, including protection against unscoped delete_all operations.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the three primary fixes: knowledge scope enforcement, async persistence offloading, and tool schema handling.
Out of Scope Changes check ✅ Passed All changes support the linked issue objectives and remain within src/praisonai-agents/praisonaiagents.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/issue-3834-20260810-0717

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR aligns knowledge-adapter deletion scope enforcement, moves async assistant-message persistence off the event-loop thread, and makes shared tool-schema generation omit variadic parameters.

  • Adds a shared scope requirement and applies it to Chroma and SQLite bulk deletion.
  • Awaits thread-offloaded assistant-message persistence across async chat completion branches.
  • Excludes *args and **kwargs from generated LLM parameter schemas.

Confidence Score: 5/5

The PR appears safe to merge, with no concrete changed-code defect identified.

The new scope checks execute before broad adapter exception handling, async persistence remains awaited, and variadic omission is consistent with the existing tool-definition path.

Important Files Changed

Filename Overview
src/praisonai-agents/praisonaiagents/agent/chat_mixin.py Replaces six synchronous assistant-message persistence calls in async chat branches with awaited async wrappers.
src/praisonai-agents/praisonaiagents/agent/memory_mixin.py Adds an async wrapper that offloads synchronous message persistence through asyncio.to_thread.
src/praisonai-agents/praisonaiagents/knowledge/adapters/factories.py Requires tenant scope before Chroma or SQLite bulk deletion while preserving their existing scoped deletion behavior.
src/praisonai-agents/praisonaiagents/knowledge/protocols.py Adds the shared require_scope helper and raises the existing typed scope error for unscoped operations.
src/praisonai-agents/praisonaiagents/tools/schema.py Omits positional and keyword variadic parameters from LLM-facing JSON schemas, matching the sibling schema builder.

Reviews (1): Last reviewed commit: "fix: enforce knowledge scope, offload as..." | Re-trigger Greptile

@MervinPraison

Copy link
Copy Markdown
Owner

@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAI (not a fork), you are able to make modifications to this branch and push directly. SCOPE: Focus ONLY on Python packages (praisonaiagents, praisonai). Do NOT modify praisonai-rust or praisonai-ts. Read ALL comments above from Gemini, Qodo, CodeRabbit, and Copilot carefully before responding.

Phase 1: Review per AGENTS.md

  1. Protocol-driven: check heavy implementations vs core SDK
  2. Backward compatible: ensure zero feature regressions
  3. Performance: no hot-path regressions
  4. SDK value: review in depth whether the change genuinely adds value to the SDK — never add features for the sake of adding them. It must strengthen the SDK (simpler, more user-friendly, robust, world-class, secure). If it does not clearly add value, request changes or recommend rejecting/closing rather than merging scope creep
  5. Do not bloat the Agent class with additional params — only if absolutely required; we already support many params.
  6. Repo routing: agent-callable tools → PraisonAI-Tools; lifecycle plugins → PraisonAI-Plugins; optional sandbox backends → PraisonAI-Plugins (praisonai.sandbox entry point) — request changes if wrongly added to praisonaiagents/

Phase 2: FIX Valid Issues
7. For any VALID bugs or architectural flaws found by Gemini, CodeRabbit, Qodo, Copilot, or any other reviewer: implement the fix
8. Also independently identify and fix any gaps or issues you find in the changed code — do not rely only on prior reviewer feedback
9. Push all code fixes directly to THIS branch (do NOT create a new PR)
10. Comment a summary of exact files modified and what you skipped

Phase 3: Final Verdict
11. If all issues are resolved, approve the PR / close the Issue
12. If blocking issues remain, request changes / leave clear action items

@MervinPraison MervinPraison added pipeline/awaiting-merge-gate FINAL done; waiting for merge gate / CI pipeline/blocked:cooldown Blocked: post-push or @claude cooldown and removed pipeline/final-claude-pending Reviews done; waiting for FINAL @claude pipeline/blocked:no-final Blocked: no FINAL @claude trigger yet labels Aug 10, 2026
@praisonai-triage-agent

praisonai-triage-agent Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Claude finished @MervinPraison's task —— View job


Final Architecture Review — PR #3835 — ✅ APPROVE

  • Read AGENTS.md + guidelines
  • Review changed files (5)
  • Critical analysis (protocol-driven, backward-compat, perf, SDK value)
  • Verify behaviour + run tests
  • Final verdict

Phase 1 — Architecture review

Criterion Verdict
Protocol-driven require_scope is a stdlib-only helper in knowledge/protocols.py (core-appropriate, no heavy deps). Adapters call it; no logic leaks into core.
Backward compatible ✅ Scoped delete_all() unchanged. Only unscoped delete_all() now raises ScopeRequiredError — this is the intended, safer behaviour matching the mem0 backend. _apersist_message is additive.
Performance ✅ Async persist offloaded via asyncio.to_thread, unblocking the event loop — a hot-path improvement. Sync paths untouched (no overhead).
SDK value ✅ All three are genuine correctness/safety fixes (data-loss/leak prevention, non-blocking achat(), valid tool schemas). No new params, no Agent-class bloat, no scope creep.
Routing ✅ Correctly in praisonaiagents/ — these are core protocol/introspection/persistence concerns, not agent tools or lifecycle plugins.

Phase 2 — Correctness verification (independent)

  • Gap 1: Chroma + SQLite delete_all call require_scope(...) before the broad try/except, so the error propagates rather than being swallowed. ✅
  • Gap 2: All 6 assistant persists inside async _achat_implawait _apersist_message. Confirmed the sync sites at lines 4252/4295/4308 live inside the sync _start_stream generator (def @3989), so leaving them sync is correct.
    • Note (not a defect, out of scope): the async path already didn't persist the user turn (only the sync _chat_impl does at 2774/2926). This asymmetry pre-dates this PR; the PR faithfully converts only the existing sync→async calls. Flagging for a possible follow-up, not blocking.
  • Gap 3: build_parameters_schema skips VAR_POSITIONAL/VAR_KEYWORD, matching build_tool_definition. ✅

Behavioural + test verification

f1(query, **kwargs)      -> props=['query'] required=['query']   # kwargs omitted
f2(query, *args, flag=…) -> props=['query','flag'] required=['query']  # args omitted
unscoped require_scope   -> raises ScopeRequiredError
scoped require_scope     -> passes
_apersist_message        -> coroutine (offloads to thread)

pytest tests/test_tool_schema_parity.py tests/unit/knowledge/test_adapters.py27 passed, 1 skipped. (Other collection errors in the sandbox are pre-existing missing-dep issues unrelated to this PR.)

Phase 3 — Verdict

No changes required — approving. The PR is minimal, protocol-driven, backward-compatible, and fixes three real safety/correctness/performance gaps without adding surface area. Files modified by me: none.

Job run • Branch: claude/issue-3834-20260810-0717

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
src/praisonai-agents/praisonaiagents/tools/schema.py (1)

241-251: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add regression coverage for variadic filtering.

Verify that a signature such as (value, *args, **kwargs) exposes only value in properties and required. Cover both src/praisonai-agents/praisonaiagents/tools/base.py and src/praisonai-agents/praisonaiagents/tools/decorator.py, because both call build_parameters_schema.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai-agents/praisonaiagents/tools/schema.py` around lines 241 - 251,
Add regression tests for variadic parameter filtering in both the base and
decorator tool builders that call build_parameters_schema. Use a function
signature of (value, *args, **kwargs) and assert that only value appears in both
the generated properties and required fields, with variadic arguments excluded.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/praisonai-agents/praisonaiagents/agent/chat_mixin.py`:
- Around line 3495-3498: Complete async persistence in the chat turn handlers:
after every successful async user-message append to chat_history, including the
unified and custom-provider branches, call _apersist_message for the user with
normalized_content. After each custom-provider assistant response append, call
_apersist_message for the assistant with response_text. Preserve the existing
sync/async APIs and use async persistence without changing message ordering.
- Around line 3495-3498: Update the async chat flow containing
`_build_messages()` and `_apersist_message()` to initialize persistence first:
run `_init_db_session()` and `_init_session_store()` via `asyncio.to_thread()`,
matching the sync path’s setup and ensuring `_session_store` and `_session_id`
are ready before history construction or the first write.

In `@src/praisonai-agents/praisonaiagents/agent/memory_mixin.py`:
- Around line 438-458: Serialize the complete persistence operation in
_apersist_message using an instance-owned asyncio.Lock initialized once for the
owning event loop, then acquire it before calling
asyncio.to_thread(self._persist_message, ...). Ensure concurrent achat() calls
sharing the agent execute _persist_message, including index and statistics
updates, in order while retaining thread offloading for blocking I/O.

In `@src/praisonai-agents/praisonaiagents/knowledge/adapters/factories.py`:
- Around line 371-376: Update ChromaKnowledgeAdapter.delete_all to perform
scoped deletion directly through collection.delete(where=...) using the
applicable user_id, agent_id, and run_id filter, rather than relying on get_all
and its limited peek results. Ensure retrieval or deletion failures propagate
instead of being converted into an empty successful deletion, while preserving
the True result after a successful delete.

In `@src/praisonai-agents/praisonaiagents/knowledge/protocols.py`:
- Around line 215-220: Update the custom message in the ScopeRequiredError
construction for this scope-validation operation to include the backend
identifier alongside the existing operation and required-scope details. Preserve
the current remediation hint and pass the same backend value already supplied to
the exception.

---

Nitpick comments:
In `@src/praisonai-agents/praisonaiagents/tools/schema.py`:
- Around line 241-251: Add regression tests for variadic parameter filtering in
both the base and decorator tool builders that call build_parameters_schema. Use
a function signature of (value, *args, **kwargs) and assert that only value
appears in both the generated properties and required fields, with variadic
arguments excluded.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e0951210-d9d6-48ba-8e81-0d24ab673d25

📥 Commits

Reviewing files that changed from the base of the PR and between 7b1ddd4 and 07ae45f.

📒 Files selected for processing (5)
  • src/praisonai-agents/praisonaiagents/agent/chat_mixin.py
  • src/praisonai-agents/praisonaiagents/agent/memory_mixin.py
  • src/praisonai-agents/praisonaiagents/knowledge/adapters/factories.py
  • src/praisonai-agents/praisonaiagents/knowledge/protocols.py
  • src/praisonai-agents/praisonaiagents/tools/schema.py

Comment on lines +3495 to +3498
# Persist assistant message to DB (offloaded to a
# worker thread so file-locked disk I/O doesn't
# block the event loop on this async turn).
await self._apersist_message("assistant", response_text)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Complete async persistence coverage.

These changes persist assistant responses in the unified branch, but the async user turn at Lines 3408-3413 is only appended to chat_history. The custom-provider branch at Lines 3287-3292 and 3369 also updates only in-memory history. The sync path persists the corresponding turns at Lines 2770-2774 and 2861-2863.

After initialization is fixed, async sessions can still omit user messages, and custom-provider sessions can omit both sides of the exchange. Add _apersist_message("user", normalized_content) after each successful user append. Add _apersist_message("assistant", response_text) after the custom-provider response append.

As per coding guidelines, preserve sync/async API behavior and use async persistence for all async I/O.

Also applies to: 3515-3517, 3573-3574, 3604-3605, 3623-3624, 3673-3674

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai-agents/praisonaiagents/agent/chat_mixin.py` around lines 3495 -
3498, Complete async persistence in the chat turn handlers: after every
successful async user-message append to chat_history, including the unified and
custom-provider branches, call _apersist_message for the user with
normalized_content. After each custom-provider assistant response append, call
_apersist_message for the assistant with response_text. Preserve the existing
sync/async APIs and use async persistence without changing message ordering.

Source: Coding guidelines


🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Initialize persistence before the async chat path uses the wrapper.

The async path does not call _init_db_session() or _init_session_store(). The sync path calls both at Lines 2618-2623 before using history. For a session_id-backed JSON session, _session_store can remain unset, so _persist_message() returns without writing. DB-backed sessions can also lack the generated or restored _session_id.

Initialize the persistence backends before _build_messages() and the first message write. Run the synchronous initializers through asyncio.to_thread().

Suggested initialization
         llm_prompt = self._build_multimodal_prompt(prompt, attachments) if attachments else prompt
+        import asyncio
+        await asyncio.to_thread(self._init_db_session)
+        await asyncio.to_thread(self._init_session_store)

As per coding guidelines, async I/O must not block the event loop.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai-agents/praisonaiagents/agent/chat_mixin.py` around lines 3495 -
3498, Update the async chat flow containing `_build_messages()` and
`_apersist_message()` to initialize persistence first: run `_init_db_session()`
and `_init_session_store()` via `asyncio.to_thread()`, matching the sync path’s
setup and ensuring `_session_store` and `_session_id` are ready before history
construction or the first write.

Source: Coding guidelines

Comment on lines +438 to +458
async def _apersist_message(
self,
role: str,
content: str,
tool_calls=None,
tool_call_id: Optional[str] = None,
):
"""Async wrapper for :meth:`_persist_message`.

The default JSON session store performs a file-locked, blocking
read-modify-write to disk on every turn. Calling ``_persist_message``
directly from ``_achat_impl`` would stall the entire event loop (other
agents, streaming, background tasks) for the duration of that I/O on
every user/assistant/tool turn. Offloading to a worker thread — the
same treatment ``_persist_compaction_checkpoint`` already gets — keeps
``achat()`` non-blocking as documented.
"""
import asyncio
await asyncio.to_thread(
self._persist_message, role, content, tool_calls, tool_call_id
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Serialize per-agent persistence calls.

When two achat() calls share an agent or session, asyncio.to_thread can run _persist_message concurrently in different worker threads. _persist_message writes the message, updates _auto_save_last_index, and persists session statistics as separate operations. The file lock described in the docstring does not preserve logical message order across calls.

Serialize the full operation with an instance-owned asyncio.Lock or an ordered per-session queue. Initialize the coordination primitive once for the owning event loop.

As per coding guidelines, use asyncio primitives rather than threading for coordination.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai-agents/praisonaiagents/agent/memory_mixin.py` around lines 438
- 458, Serialize the complete persistence operation in _apersist_message using
an instance-owned asyncio.Lock initialized once for the owning event loop, then
acquire it before calling asyncio.to_thread(self._persist_message, ...). Ensure
concurrent achat() calls sharing the agent execute _persist_message, including
index and statistics updates, in order while retaining thread offloading for
blocking I/O.

Source: Coding guidelines

Comment on lines +371 to +376
# Get filtered items and delete them
all_items = self.get_all(user_id=user_id, agent_id=agent_id, run_id=run_id)
item_ids = [item.id for item in all_items.results]
if item_ids:
self.collection.delete(ids=item_ids)
return True

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '305,378p' src/praisonai-agents/praisonaiagents/knowledge/adapters/factories.py
rg -n -C 4 --glob '*.py' 'def delete_all\(|ChromaKnowledgeAdapter|collection\.(get|delete|peek)\(' src/praisonai-agents

Repository: MervinPraison/PraisonAI

Length of output: 18660


🌐 Web query:

ChromaDB collection delete method support where parameter ids where metadata

💡 Result:

The ChromaDB collection delete method supports both ids and metadata-based filtering, along with document content filtering. You can remove records by specifying their IDs, metadata, or document content [1][2]. The delete method supports the following parameters: - ids: An optional list of strings representing the IDs of the specific records you want to delete [2][3]. - where: An optional dictionary used as a metadata filter to delete records that match specific metadata criteria [2][3][4]. - where_document: An optional dictionary used to filter and delete records based on their document content (e.g., using operators like $contains) [1][2][3]. - limit: An optional integer that specifies the maximum number of records to delete. This parameter can only be used in conjunction with where or where_document filters [3][5]. Note that these filters (where, where_document) are applied to the entire collection to identify records for deletion [2][3]. If no IDs or filters are provided, the operation will raise a ValueError [2][3]. While the delete method removes records, it keeps the collection itself intact; to delete an entire collection, you must use the delete_collection method instead [1][6].

Citations:


Use a ChromaDB-side delete for scoped deletion.

ChromaKnowledgeAdapter.delete_all builds the deletion key from get_all, which checks at most 100 unfiltered records with collection.peek(limit=100), and turns retrieval failures into empty results. A scope with records beyond the first page can return True while keeping those records. Use collection.delete(where=...) with the scope filter or page scoped IDs, and keep retrieval failures as failures.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai-agents/praisonaiagents/knowledge/adapters/factories.py` around
lines 371 - 376, Update ChromaKnowledgeAdapter.delete_all to perform scoped
deletion directly through collection.delete(where=...) using the applicable
user_id, agent_id, and run_id filter, rather than relying on get_all and its
limited peek results. Ensure retrieval or deletion failures propagate instead of
being converted into an empty successful deletion, while preserving the True
result after a successful delete.

Comment on lines +215 to +220
raise ScopeRequiredError(
message=(
f"{operation} requires at least one of 'user_id', 'agent_id', "
f"or 'run_id' to scope the {operation}."
),
backend=backend,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Include the backend in the exception message.

The custom message bypasses ScopeRequiredError's backend-aware default message. As a result, str(error) does not identify the failing backend. Include backend in this message for direct diagnostics.

Proposed fix
-                f"or 'run_id' to scope the {operation}."
+                f"or 'run_id' to scope the {operation}"
+                f"{f' for the {backend} backend' if backend else ''}."

As per coding guidelines, “Fail fast with clear exceptions, include remediation hints, propagate agent/tool/session context.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
raise ScopeRequiredError(
message=(
f"{operation} requires at least one of 'user_id', 'agent_id', "
f"or 'run_id' to scope the {operation}."
),
backend=backend,
raise ScopeRequiredError(
message=(
f"{operation} requires at least one of 'user_id', 'agent_id', "
f"or 'run_id' to scope the {operation}"
f"{f' for the {backend} backend' if backend else ''}."
),
backend=backend,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai-agents/praisonaiagents/knowledge/protocols.py` around lines 215
- 220, Update the custom message in the ScopeRequiredError construction for this
scope-validation operation to include the backend identifier alongside the
existing operation and required-scope details. Preserve the current remediation
hint and pass the same backend value already supplied to the exception.

Source: Coding guidelines

@praisonai-triage-agent praisonai-triage-agent Bot removed pipeline/blocked:ci Blocked: CI not green on HEAD pipeline/blocked:cooldown Blocked: post-push or @claude cooldown labels Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pipeline/awaiting-merge-gate FINAL done; waiting for merge gate / CI pipeline/blocked:manual-review Blocked: requires manual review

Projects

None yet

1 participant