Skip to content

Feat: Agent api#14157

Merged
wangq8 merged 45 commits into
infiniflow:mainfrom
Magicbook1108:main
Apr 24, 2026
Merged

Feat: Agent api#14157
wangq8 merged 45 commits into
infiniflow:mainfrom
Magicbook1108:main

Conversation

@Magicbook1108
Copy link
Copy Markdown
Contributor

@Magicbook1108 Magicbook1108 commented Apr 16, 2026

What problem does this PR solve?

  1. List agents
    Prev API:

    • /v1/canvas/list GET
    • /api/v1/agents GET
      Current API: /api/v2/agents GET
  2. Get canvas template
    Prev API: /v1/canvas/templates GET
    Current API: /api/v2/agents/templates GET

  3. Delete an agent
    Prev API:

    • /v1/canvas/rm POST
    • /api/v1/agents/<agent_id> DELETE
      Current API: /api/v2/agents/<agent_id> DELETE
  4. Update an agent
    Prev API:

    • /api/v1/agents/<agent_id> PUT
    • /v1/canvas/setting POST
      Current API: /api/v2/agents/<agent_id> PATCH
  5. Create an agent
    Prev API:

    • /v1/canvas/set POST
    • /api/v1/agents POST
      Current API: /api/v2/agents POST
  6. Get an agent
    Prev API:

    • /v1/canvas/get/<canvas_id> GET
      Current API: /api/v2/agents/<agent_id> GET
  7. Reset an agent
    Prev API:

    • /v1/canvas/reset POST
      Current API: /api/v2/agents/<agent_id>/reset POST
  8. Upload a file to an agent
    Prev API:

    • /v1/canvas/upload/<canvas_id> POST
      Current API: /api/v2/agents/<agent_id>/upload POST
  9. Input form
    Prev API:

    • /v1/canvas/input_form GET
      Current API: /api/v2/agents/<agent_id>/components/<component_id>/input-form GET
  10. Debug an agent
    Prev API:

    • /v1/canvas/debug POST
      Current API: /api/v2/agents/<agent_id>/components/<component_id>/debug POST
  11. Trace an agent
    Prev API:

    • /v1/canvas/trace GET
      Current API: /api/v2/agents/<agent_id>/logs/<message_id> GET
  12. Get an agent version list
    Prev API:

    • /v1/canvas/getlistversion/<canvas_id>
      Current API: /api/v2/agents/<agent_id>/versions GET
  13. Get a version of agent
    Prev API:

    • /v1/canvas/getversion/<version_id>
      Current API: /api/v2/agents/<agent_id>/versions/<version_id> GET
  14. Test db connection
    Prev API:

    • /v1/canvas/test_db_connect POST
      Current API: /api/v2/agents/test_db_connection
  15. Rerun the agent
    Prev API:

    • /v1/canvas/rerun POST
      Current API: /api/v2/agents/rerun POST
  16. Get prompts
    Prev API:

    • /v1/canvas/prompts GET
      Current API: /api/v2/agents/prompts GET

Type of change

  • New Feature (non-breaking change which adds functionality)

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Apr 16, 2026
@Magicbook1108 Magicbook1108 marked this pull request as draft April 16, 2026 09:06
@Magicbook1108 Magicbook1108 added the ci Continue Integration label Apr 16, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 16, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Removed canvas-specific handlers and replaced them with agent-focused REST endpoints; updated Python SDK client, backend SDK module, frontend API mappings, hooks, types, docs, and tests to call and handle the new /agents endpoints and their response shape.

Changes

Cohort / File(s) Summary
Backend — canvas handlers removed
api/apps/canvas_app.py
Removed authenticated POST /rm, GET /get/<canvas_id>, and GET /list route handlers and imports tied to those flows.
Backend — new agent REST API
api/apps/restful_apis/agent_api.py
Added GET /agents, GET /agents/<agent_id>, and DELETE /agents/<agent_id> handlers (tenant/owner resolution, access checks, canvas retrieval, replica bootstrap, version lookup, DSL normalization, optional Knowledgebase dataset enrichment).
Backend SDK adjustments
api/apps/sdk/agents.py
Removed legacy /agents GET and /agents/<agent_id> DELETE handlers from SDK module (request parsing and deletion logic removed).
Python SDK client
sdk/python/ragflow_sdk/ragflow.py
Added RAGFlow.get_agent(agent_id) and updated RAGFlow.list_agents(...) to call get_agent when id provided and to parse res.get("data", {}).get("canvas", []) for list responses.
Frontend — API mappings
web/src/utils/api.ts
Replaced listCanvas/getCanvas/removeCanvas mappings with listAgents and deleteAgent(agentId); changed fetchCanvas(id) to /agents/{id}.
Frontend — services & hooks
web/src/services/agent-service.ts, web/src/hooks/use-agent-request.ts
Switched service calls from listCanvaslistAgents, introduced buildAgentListParams helper, updated delete hook to use deleteAgent(agentId) (single id), and adjusted mutation param types.
Frontend — types
web/src/interfaces/database/agent.ts
Extended IPipeLineListRequest with optional ext?: string.
Frontend — UI call sites
web/src/pages/agents/agent-dropdown.tsx
Changed delete call-site to pass agent.id (string) instead of [agent.id] (string[]).
Docs
docs/references/python_api_reference.md
Documented RAGFlow.get_agent(agent_id), updated examples to prefer get_agent, changed orderby default to update_time, and corrected title label.
Tests
test/.../test_agent_crud_unit.py
Adjusted unit test to new response schema where data is an object containing canvas and total, and updated expected default query params.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant API as AgentAPI (manager)
  participant Tenant as TenantService
  participant UserCanvas as UserCanvasService
  participant Replica as CanvasReplicaService
  participant KB as KnowledgebaseService

  Client->>API: GET /agents?params
  API->>Tenant: (if owner_ids empty) get_joined_tenants_by_user_id(user_id)
  Tenant-->>API: tenant_ids
  API->>UserCanvas: get_by_tenant_ids(tenant_ids, params)
  UserCanvas-->>API: {canvas, total}
  API-->>Client: {canvas, total}

  Client->>API: GET /agents/{agent_id}
  API->>UserCanvas: accessible(agent_id, tenant_id)
  UserCanvas-->>API: canvas_meta
  API->>Replica: bootstrap(dsl, metadata)
  Replica-->>API: runtime_replica / error
  API->>UserCanvas: list_canvas_versions(agent_id)
  UserCanvas-->>API: versions
  API->>KB: (if DataFlow) query datasets
  KB-->>API: datasets
  API-->>Client: assembled agent payload
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • JinHai-CN
  • yingfeng
  • yuzhichang

Poem

🐇 I hopped from canvas to agent lanes,
New routes, SDK calls, and docs in trains,
Frontend, tests, services sing,
Bootstrap, versions, datasets bring,
A rabbit cheers these tidy gains!

🚥 Pre-merge checks | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning PR description is incomplete and misaligned with actual changes. It lists 16 API migration scenarios but only 3 endpoints are actually implemented in this PR (list/get/delete agents). Update the description to accurately reflect only the implemented changes: moving list/get/delete agent endpoints from /v1/canvas/* and /api/v1/agents/* to /api/v1/agents. Remove or clearly mark unimplemented operations (create, update, reset, upload, etc.) as out of scope.
Title check ❓ Inconclusive The PR title 'Feat: Agent api' is vague and generic, lacking specificity about what the API changes accomplish. Consider using a more specific title such as 'Feat: Add agent listing and retrieval REST API endpoints' to clearly describe the main changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

@dosubot dosubot Bot added 🐖api The modified files are located under directory 'api/apps/sdk' 💞 feature Feature request, pull request that fullfill a new feature. labels Apr 16, 2026
@Magicbook1108 Magicbook1108 marked this pull request as ready for review April 16, 2026 09:12
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/src/hooks/use-agent-request.ts (1)

192-205: ⚠️ Potential issue | 🟠 Major

Add FetchAllAgentList to cache invalidation after agent mutations.

useFetchAllAgentList() uses query key AgentApiAction.FetchAllAgentList (line 194), but none of the agent mutations invalidate it. The create, update, and delete mutations invalidate only AgentApiAction.FetchAgentListByPage (lines 228, 252, 348), leaving any dropdown or selector backed by the full list with stale data after mutations.

Add queryClient.invalidateQueries({ queryKey: [AgentApiAction.FetchAllAgentList] }) to all three mutation blocks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/hooks/use-agent-request.ts` around lines 192 - 205, The full-agent
list query key AgentApiAction.FetchAllAgentList (used in useFetchAllAgentList)
is not being invalidated after agent create/update/delete mutations; update the
three mutation handlers that currently call queryClient.invalidateQueries({
queryKey: [AgentApiAction.FetchAgentListByPage] }) to also call
queryClient.invalidateQueries({ queryKey: [AgentApiAction.FetchAllAgentList] })
so the cache for useFetchAllAgentList is refreshed after create, update, and
delete operations; locate these changes in the mutation blocks for createAgent,
updateAgent, and deleteAgent in this file and add the extra invalidateQueries
call for AgentApiAction.FetchAllAgentList.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/apps/restful_apis/agent_api.py`:
- Around line 33-69: The new list_agents flow lacks server-side logging; add
structured logs at key points in list_agents: log incoming request scope
(including current_user.id, tenant_id, keywords, owner_ids, page/page_size,
orderby, desc) at function start, log access denial or empty-owners branching
when TenantService.get_joined_tenants_by_user_id returns empty or when
current_user is unauthorized, log bootstrap/Service call failures and exceptions
around TenantService.get_joined_tenants_by_user_id and
UserCanvasService.get_by_tenant_ids (including caught exception details), and
log the final response summary before returning via get_json_result; use the
existing app logger (or processLogger) and include identifiers like list_agents,
TenantService.get_joined_tenants_by_user_id,
UserCanvasService.get_by_tenant_ids, and get_json_result to aid tracing.
- Around line 57-67: The branch currently passes raw owner_ids to
UserCanvasService.get_by_tenant_ids() and forces pagination to zeros; instead,
first filter/validate owner_ids against the caller's allowed tenants (e.g., call
an auth helper like AuthService.filter_authorized_tenants(owner_ids,
current_user) or TenantService.get_allowed_tenant_ids(current_user)) and use
that returned, authorized list when calling
UserCanvasService.get_by_tenant_ids(), and restore the original pagination
arguments (page and page_size) rather than passing 0,0 so pagination is
preserved; also handle the case where the authorized list is empty (return empty
result or appropriate error) before calling get_by_tenant_ids().

In `@sdk/python/ragflow_sdk/ragflow.py`:
- Around line 240-257: The current list_agents implementation filters by title
locally per page, causing false negatives for agents on other pages; update the
GET request params (the dict passed to self.get in the method that constructs
Agent objects) to include "title": title when title is provided so the server
can do an exact-title filter, or alternatively implement server-side-equivalent
behavior by looping over paginated results (calling self.get repeatedly with
page++ until found or no more data) and then constructing Agent(self, data) —
update the code paths that call self.get and the result_list building
(referencing the self.get call and Agent class usage) to use one of these fixes.

---

Outside diff comments:
In `@web/src/hooks/use-agent-request.ts`:
- Around line 192-205: The full-agent list query key
AgentApiAction.FetchAllAgentList (used in useFetchAllAgentList) is not being
invalidated after agent create/update/delete mutations; update the three
mutation handlers that currently call queryClient.invalidateQueries({ queryKey:
[AgentApiAction.FetchAgentListByPage] }) to also call
queryClient.invalidateQueries({ queryKey: [AgentApiAction.FetchAllAgentList] })
so the cache for useFetchAllAgentList is refreshed after create, update, and
delete operations; locate these changes in the mutation blocks for createAgent,
updateAgent, and deleteAgent in this file and add the extra invalidateQueries
call for AgentApiAction.FetchAllAgentList.
🪄 Autofix (Beta)

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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3d00b208-3ffa-4525-aaee-9049432912a1

📥 Commits

Reviewing files that changed from the base of the PR and between 901023a and add88ca.

📒 Files selected for processing (9)
  • api/apps/canvas_app.py
  • api/apps/restful_apis/agent_api.py
  • api/apps/sdk/agents.py
  • docs/references/python_api_reference.md
  • sdk/python/ragflow_sdk/ragflow.py
  • web/src/hooks/use-agent-request.ts
  • web/src/interfaces/database/agent.ts
  • web/src/services/agent-service.ts
  • web/src/utils/api.ts
💤 Files with no reviewable changes (2)
  • api/apps/sdk/agents.py
  • api/apps/canvas_app.py

Comment on lines +33 to +69
def list_agents(tenant_id):
keywords = request.args.get("keywords", "")
canvas_category = request.args.get("canvas_category")
owner_ids = [item for item in request.args.get("owner_ids", "").strip().split(",") if item]

page_number = int(request.args.get("page", 0))
items_per_page = int(request.args.get("page_size", 0))
order_by = request.args.get("orderby", "create_time")
desc = str(request.args.get("desc", "true")).lower() != "false"

if not owner_ids:
tenants = TenantService.get_joined_tenants_by_user_id(current_user.id)
tenants = [member["tenant_id"] for member in tenants]
tenants.append(current_user.id)
canvas, total = UserCanvasService.get_by_tenant_ids(
tenants,
current_user.id,
page_number,
items_per_page,
order_by,
desc,
keywords,
canvas_category,
)
else:
canvas, total = UserCanvasService.get_by_tenant_ids(
owner_ids,
current_user.id,
0,
0,
order_by,
desc,
keywords,
canvas_category,
)

return get_json_result(data={"canvas": canvas, "total": total})
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.

⚠️ Potential issue | 🟡 Minor

Add server-side logging for these new agent flows.

The new list/get endpoints have no logs for request scope, access denials, or bootstrap failures, which will make production debugging and audit trails much harder.

As per coding guidelines, "Add logging for new flows".

Also applies to: 75-110

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/apps/restful_apis/agent_api.py` around lines 33 - 69, The new list_agents
flow lacks server-side logging; add structured logs at key points in
list_agents: log incoming request scope (including current_user.id, tenant_id,
keywords, owner_ids, page/page_size, orderby, desc) at function start, log
access denial or empty-owners branching when
TenantService.get_joined_tenants_by_user_id returns empty or when current_user
is unauthorized, log bootstrap/Service call failures and exceptions around
TenantService.get_joined_tenants_by_user_id and
UserCanvasService.get_by_tenant_ids (including caught exception details), and
log the final response summary before returning via get_json_result; use the
existing app logger (or processLogger) and include identifiers like list_agents,
TenantService.get_joined_tenants_by_user_id,
UserCanvasService.get_by_tenant_ids, and get_json_result to aid tracing.

Comment thread api/apps/restful_apis/agent_api.py Outdated
Comment thread sdk/python/ragflow_sdk/ragflow.py
@dosubot dosubot Bot added size:XS This PR changes 0-9 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Apr 16, 2026
@Magicbook1108 Magicbook1108 reopened this Apr 16, 2026
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XS This PR changes 0-9 lines, ignoring generated files. labels Apr 16, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 16, 2026

Codecov Report

❌ Patch coverage is 58.33333% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 95.30%. Comparing base (7817b0d) to head (00175af).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
sdk/python/ragflow_sdk/ragflow.py 50.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #14157      +/-   ##
==========================================
- Coverage   95.97%   95.30%   -0.67%     
==========================================
  Files          10       10              
  Lines         695      703       +8     
  Branches      111      112       +1     
==========================================
+ Hits          667      670       +3     
- Misses         11       16       +5     
  Partials       17       17              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
test/testcases/test_sdk_api/test_agent_management/test_agent_crud_unit.py (1)

41-63: ⚠️ Potential issue | 🟡 Minor

Please add coverage for the new get_agent() / list_agents(id=...) path.

This update only exercises the paginated /agents flow. The new /agents/{agent_id} behavior and the title-mismatch [] branch are still untested, so regressions in the actual feature added by this PR will slip through.

Based on learnings, "Applies to tests/**/*.py : Add/adjust tests for behavior changes".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/testcases/test_sdk_api/test_agent_management/test_agent_crud_unit.py`
around lines 41 - 63, Add test coverage for the new single-agent path by
exercising RAGFlow.get_agent() and list_agents(id=...) and the title-mismatch
branch: monkeypatch client.get to return a success payload for
"/agents/{agent_id}" and assert the returned object is an Agent with the
expected id/title (use get_agent and list_agents(id="agent-1") calls), then
monkeypatch client.get to return an empty data.canvas (or a payload where the
title does not match) and assert list_agents(title="Nonexistent") yields an
empty list; also keep the existing error-case assertion by returning
{"code":1,"message":"list boom"} for the paginated flow to ensure exceptions
still bubble up.
♻️ Duplicate comments (1)
sdk/python/ragflow_sdk/ragflow.py (1)

240-257: ⚠️ Potential issue | 🟠 Major

Pass title through to /agents instead of filtering one page locally.

When title is set, this code still fetches a single paginated page and filters that page in Python, so a matching agent on page 2+ is returned as []. The request should include title or the SDK should keep paginating until exhausted.

Suggested fix
         res = self.get(
             "/agents",
             {
                 "page": page,
                 "page_size": page_size,
                 "orderby": orderby,
                 "desc": desc,
+                "title": title,
             },
         )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sdk/python/ragflow_sdk/ragflow.py` around lines 240 - 257, The current agents
list call paginates a single page then filters locally, which misses matches on
later pages; update the GET request in the method that calls self.get("/agents",
...) to include the title parameter when title is provided (i.e., add "title":
title into the request params) so the server can filter, or alternatively
implement server-pagination by looping pages (incrementing page and aggregating
results_list until no more data) instead of only filtering the first page;
modify the parameters passed into self.get and remove the local single-page
title filter (the block that checks data.get("title") and continues) if you opt
to pass the title to the API.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@sdk/python/ragflow_sdk/ragflow.py`:
- Around line 233-266: The new remote-call flows in list_agents and get_agent
must log request context and failure details before raising; modify list_agents
(when calling self.get("/agents", {...}) and on non-zero res.get("code") path)
to log the request params (page, page_size, orderby, desc, title, id if used)
and the full response body/status, and modify get_agent (when calling
self.get(f"/agents/{agent_id}") and on non-zero res.get("code") path) to log the
agent_id and the full response body/status; use the module/class logger (e.g.,
self.logger.error or a module logging.getLogger(__name__)) to emit an
error-level message that includes the context and res contents before raising
the Exception.
- Around line 252-257: The SDK's list_agents implementation assumes res["data"]
is a dict with a "canvas" key and will crash if the backend returns a list;
update the logic in list_agents to handle both shapes: detect whether data (the
value from res.get("data")) is a dict and use data.get("canvas", []) otherwise
if it's a list treat it as the agent list directly, then iterate that list and
construct Agent(self, item) (avoid calling .get() on a list). Ensure you
reference the variables/data_list, data, and the Agent(self, ...) construction
when making the change.

---

Outside diff comments:
In `@test/testcases/test_sdk_api/test_agent_management/test_agent_crud_unit.py`:
- Around line 41-63: Add test coverage for the new single-agent path by
exercising RAGFlow.get_agent() and list_agents(id=...) and the title-mismatch
branch: monkeypatch client.get to return a success payload for
"/agents/{agent_id}" and assert the returned object is an Agent with the
expected id/title (use get_agent and list_agents(id="agent-1") calls), then
monkeypatch client.get to return an empty data.canvas (or a payload where the
title does not match) and assert list_agents(title="Nonexistent") yields an
empty list; also keep the existing error-case assertion by returning
{"code":1,"message":"list boom"} for the paginated flow to ensure exceptions
still bubble up.

---

Duplicate comments:
In `@sdk/python/ragflow_sdk/ragflow.py`:
- Around line 240-257: The current agents list call paginates a single page then
filters locally, which misses matches on later pages; update the GET request in
the method that calls self.get("/agents", ...) to include the title parameter
when title is provided (i.e., add "title": title into the request params) so the
server can filter, or alternatively implement server-pagination by looping pages
(incrementing page and aggregating results_list until no more data) instead of
only filtering the first page; modify the parameters passed into self.get and
remove the local single-page title filter (the block that checks
data.get("title") and continues) if you opt to pass the title to the API.
🪄 Autofix (Beta)

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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3ad09380-407d-4745-9a7f-7848ef021419

📥 Commits

Reviewing files that changed from the base of the PR and between 5f5225f and a256811.

📒 Files selected for processing (2)
  • sdk/python/ragflow_sdk/ragflow.py
  • test/testcases/test_sdk_api/test_agent_management/test_agent_crud_unit.py

Comment thread sdk/python/ragflow_sdk/ragflow.py Outdated
Comment on lines +233 to +266
def list_agents(self, page: int = 1, page_size: int = 30, orderby: str = "update_time", desc: bool = True, id: str | None = None, title: str | None = None) -> list[Agent]:
if id is not None:
agent = self.get_agent(id)
if title is not None and agent.title != title:
return []
return [agent]

res = self.get(
"/agents",
{
"page": page,
"page_size": page_size,
"orderby": orderby,
"desc": desc,
"id": id,
"title": title,
},
)
res = res.json()
result_list = []
if res.get("code") == 0:
for data in res["data"]:
data = res.get("data") or {}
data_list = data.get("canvas", [])
for data in data_list:
if title is not None and data.get("title") != title:
continue
result_list.append(Agent(self, data))
return result_list
raise Exception(res["message"])

def get_agent(self, agent_id: str) -> Agent:
res = self.get(f"/agents/{agent_id}")
res = res.json()
if res.get("code") == 0:
return Agent(self, res["data"])
raise Exception(res["message"])
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.

⚠️ Potential issue | 🟡 Minor

Add logging in the new agent read flows.

list_agents() and get_agent() add new remote-call paths, but failures go straight to Exception(...) with no traceability. Please log the request context and the non-zero-code failure path before raising.

As per coding guidelines, "Add logging for new flows".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sdk/python/ragflow_sdk/ragflow.py` around lines 233 - 266, The new
remote-call flows in list_agents and get_agent must log request context and
failure details before raising; modify list_agents (when calling
self.get("/agents", {...}) and on non-zero res.get("code") path) to log the
request params (page, page_size, orderby, desc, title, id if used) and the full
response body/status, and modify get_agent (when calling
self.get(f"/agents/{agent_id}") and on non-zero res.get("code") path) to log the
agent_id and the full response body/status; use the module/class logger (e.g.,
self.logger.error or a module logging.getLogger(__name__)) to emit an
error-level message that includes the context and res contents before raising
the Exception.

Comment on lines +252 to 257
data = res.get("data") or {}
data_list = data.get("canvas", [])
for data in data_list:
if title is not None and data.get("title") != title:
continue
result_list.append(Agent(self, data))
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.

⚠️ Potential issue | 🔴 Critical

The new /agents parser no longer matches the SDK route contract.

The current backend snippet in api/apps/sdk/agents.py:51-68 returns data as the agent list itself, not { "canvas": ... }. In that case, Line 253 will call .get() on a list and break list_agents() at runtime.

Suggested fix
-            data = res.get("data") or {}
-            data_list = data.get("canvas", [])
-            for data in data_list:
-                if title is not None and data.get("title") != title:
+            payload = res.get("data") or []
+            data_list = payload.get("canvas", []) if isinstance(payload, dict) else payload
+            for data in data_list:
+                if title is not None and data.get("title") != title:
                     continue
                 result_list.append(Agent(self, data))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sdk/python/ragflow_sdk/ragflow.py` around lines 252 - 257, The SDK's
list_agents implementation assumes res["data"] is a dict with a "canvas" key and
will crash if the backend returns a list; update the logic in list_agents to
handle both shapes: detect whether data (the value from res.get("data")) is a
dict and use data.get("canvas", []) otherwise if it's a list treat it as the
agent list directly, then iterate that list and construct Agent(self, item)
(avoid calling .get() on a list). Ensure you reference the variables/data_list,
data, and the Agent(self, ...) construction when making the change.

@Magicbook1108 Magicbook1108 changed the title Feat: list & get agent api Feat: Agent api Apr 17, 2026
@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Apr 17, 2026
@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Apr 24, 2026
@wangq8 wangq8 merged commit c74aece into infiniflow:main Apr 24, 2026
2 of 3 checks passed
Oldcircle added a commit to Oldcircle/ragflow that referenced this pull request Apr 24, 2026
同步 infiniflow/ragflow main(v0.25.0 tag + 后续 commits)。

上游主要变更:
- REST API 大重构:user/tenant/stats/plugin/chunk/document/file2document/
  connector/langfuse/mcp/system/chat/search 全部迁到 api/apps/restful_apis/
- feat: Agent API (infiniflow#14157) / deepseek v4 (infiniflow#14346) / docling native chunking
  (infiniflow#14218) / Astraflow provider (infiniflow#14270) / title chunk 优化 (infiniflow#14325)
- refactor: doc metadata update / agent webhook → REST / 移除 legacy MCP web API
- Go 侧:retrieval_test in GO / stream think chat / zhipu thinking /
  minimax provider / balance command
- 若干 fix:think tags normalization / upload truncation / audio-video pipeline
- 7 个 ingestion_pipeline templates 重命名(Book→book 等)

冲突解决(2 处):
- CLAUDE.md:保留 fork 专属整块(Fork 信息/端口/macOS 本地/活跃文档/首次运行
  记录/Task Executor),追加上游新增的 Working Style 8 条作为独立段
- web/src/pages/dataset/testing/testing-result.tsx:保留 HEAD 版本
  (P1.7-C4 设计对齐版已内含 upstream 要加的 RAGFlowPagination + isRuned 空态
  文案,upstream 版被 HEAD 超集)

验证:
- `pytest test/agent_v2/` → 301 passed / 8 skipped(RAGFLOW_TEST_DB gate)
- 其它冲突文件 auto-merge 成功:dialog_service.py / docker/.env /
  pyproject.toml / uv.lock / locales/en.ts / dataset-table.tsx / testing-form.tsx

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
spider-yamet pushed a commit to spider-yamet/ragflow that referenced this pull request Apr 25, 2026
Resolve session.py conflict with the post-infiniflow#14157 agent API layout. Port extra_body.reference_metadata handling to api/apps/restful_apis/agent_api.py (OpenAI-compatible and session completion paths) with the prior validation and null-safety fixes.

Made-with: Cursor
@coderabbitai coderabbitai Bot mentioned this pull request Apr 28, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐖api The modified files are located under directory 'api/apps/sdk' ci Continue Integration 💞 feature Feature request, pull request that fullfill a new feature. lgtm This PR has been approved by a maintainer size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants