[PR #455] fix(sdk): normalize CompositeBackend route prefixes #675

Open
opened 2026-02-16 09:16:47 -05:00 by yindo · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/langchain-ai/deepagents/pull/455
Author: @Yo-sure
Created: 11/22/2025
Status: 🔄 Open

Base: mainHead: Yo-sure/fix-composite-backend-route-normalization


📝 Commits (2)

  • a6d4554 fix: normalize CompositeBackend route prefixes to prevent path truncation
  • 238a968 Merge remote-tracking branch 'origin/master' into Yo-sure/fix-composite-backend-route-normalization

📊 Changes

1 file changed (+12 additions, -4 deletions)

View changed files

📝 libs/deepagents/deepagents/backends/composite.py (+12 -4)

📄 Description

Problem

CompositeBackend has a path truncation bug when route prefixes are registered without a trailing slash. The bug occurs in the ls_info method at line 79:

fi["path"] = f"{route_prefix[:-1]}{fi['path']}"

This code assumes route prefixes always end with /, but the constructor accepts prefixes without trailing slashes. This causes path truncation:

Bug Example:

backend = CompositeBackend(
    default=fs,
    routes={"/workspace": workspace_backend}  # No trailing slash
)

# Bug: route_prefix[:-1] truncates the last character
# "/workspace"[:-1] = "/workspac"  ❌
# Result: /workspac/file.txt instead of /workspace/file.txt

Expected Behavior:

# "/workspace/"[:-1] = "/workspace"  ✅
# Result: /workspace/file.txt

Root Cause

The ls_info method (and grep_raw, glob_info) rely on route_prefix[:-1] to strip the trailing slash when constructing paths. However, the constructor does not enforce or normalize route prefixes to end with /, leading to inconsistent behavior.

Solution

Normalize all route prefixes to end with / in the __init__ method:

# Normalize route prefixes to end with / (e.g., "/workspace" → "/workspace/")
normalized_routes = {}
for route_prefix, backend in routes.items():
    normalized_prefix = route_prefix if route_prefix.endswith("/") else route_prefix + "/"
    normalized_routes[normalized_prefix] = backend

This ensures:

  1. Consistency: All routes are stored in a normalized format internally
  2. Backwards compatibility: Both /workspace and /workspace/ work correctly
  3. Correctness: route_prefix[:-1] logic works as designed

Testing

Reproduction

Created test_composite_bug2.py to reproduce the bug:

# Test WITHOUT trailing slash (before fix)
backend = CompositeBackend(
    default=fs,
    routes={"/workspace": workspace_backend}  # No trailing slash
)
results = backend.ls_info("/workspace")
# Bug: ["/workspac/file1.txt", "/workspac/file2.txt"]  ❌

Result after fix:

✅ ["/workspace/file1.txt", "/workspace/file2.txt"]

Verification

  • Existing unit tests pass (Windows path separators are a known issue, unrelated to this fix)
  • Both /workspace and /workspace/ route formats work correctly
  • No breaking changes to public API

Changes

  • libs/deepagents/deepagents/backends/composite.py
    • Added route prefix normalization in __init__
    • Added class and method docstrings per contributing guidelines
    • Maintains backwards compatibility

Impact

  • Users affected: Anyone using CompositeBackend with routes not ending in /
  • Severity: Medium (causes incorrect file paths in ls/glob/grep operations)
  • Breaking changes: None (pure bugfix)

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/langchain-ai/deepagents/pull/455 **Author:** [@Yo-sure](https://github.com/Yo-sure) **Created:** 11/22/2025 **Status:** 🔄 Open **Base:** `main` ← **Head:** `Yo-sure/fix-composite-backend-route-normalization` --- ### 📝 Commits (2) - [`a6d4554`](https://github.com/langchain-ai/deepagents/commit/a6d45546a8141c1264579b53b8cd5c30f0191839) fix: normalize CompositeBackend route prefixes to prevent path truncation - [`238a968`](https://github.com/langchain-ai/deepagents/commit/238a96879d29895fc6395f9619bcdef686e8ff33) Merge remote-tracking branch 'origin/master' into Yo-sure/fix-composite-backend-route-normalization ### 📊 Changes **1 file changed** (+12 additions, -4 deletions) <details> <summary>View changed files</summary> 📝 `libs/deepagents/deepagents/backends/composite.py` (+12 -4) </details> ### 📄 Description ## Problem `CompositeBackend` has a path truncation bug when route prefixes are registered without a trailing slash. The bug occurs in the `ls_info` method at line 79: ```python fi["path"] = f"{route_prefix[:-1]}{fi['path']}" ``` This code assumes route prefixes **always end with `/`**, but the constructor accepts prefixes without trailing slashes. This causes path truncation: **Bug Example:** ```python backend = CompositeBackend( default=fs, routes={"/workspace": workspace_backend} # No trailing slash ) # Bug: route_prefix[:-1] truncates the last character # "/workspace"[:-1] = "/workspac" ❌ # Result: /workspac/file.txt instead of /workspace/file.txt ``` **Expected Behavior:** ```python # "/workspace/"[:-1] = "/workspace" ✅ # Result: /workspace/file.txt ``` ## Root Cause The `ls_info` method (and `grep_raw`, `glob_info`) rely on `route_prefix[:-1]` to strip the trailing slash when constructing paths. However, the constructor does not enforce or normalize route prefixes to end with `/`, leading to inconsistent behavior. ## Solution Normalize all route prefixes to end with `/` in the `__init__` method: ```python # Normalize route prefixes to end with / (e.g., "/workspace" → "/workspace/") normalized_routes = {} for route_prefix, backend in routes.items(): normalized_prefix = route_prefix if route_prefix.endswith("/") else route_prefix + "/" normalized_routes[normalized_prefix] = backend ``` This ensures: 1. **Consistency**: All routes are stored in a normalized format internally 2. **Backwards compatibility**: Both `/workspace` and `/workspace/` work correctly 3. **Correctness**: `route_prefix[:-1]` logic works as designed ## Testing ### Reproduction Created `test_composite_bug2.py` to reproduce the bug: ```python # Test WITHOUT trailing slash (before fix) backend = CompositeBackend( default=fs, routes={"/workspace": workspace_backend} # No trailing slash ) results = backend.ls_info("/workspace") # Bug: ["/workspac/file1.txt", "/workspac/file2.txt"] ❌ ``` **Result after fix:** ``` ✅ ["/workspace/file1.txt", "/workspace/file2.txt"] ``` ### Verification - Existing unit tests pass (Windows path separators are a known issue, unrelated to this fix) - Both `/workspace` and `/workspace/` route formats work correctly - No breaking changes to public API ## Changes - **libs/deepagents/deepagents/backends/composite.py** - Added route prefix normalization in `__init__` - Added class and method docstrings per contributing guidelines - Maintains backwards compatibility ## Impact - **Users affected**: Anyone using `CompositeBackend` with routes not ending in `/` - **Severity**: Medium (causes incorrect file paths in ls/glob/grep operations) - **Breaking changes**: None (pure bugfix) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
yindo added the pull-request label 2026-02-16 09:16:47 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/deepagents#675