llamaIndex - 💡(How to fix) Fix [Feature Request]: Conditional tool parameter visibility (dynamic schema per request) [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
run-llama/llama_index#21229Fetched 2026-04-08 01:58:06
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Author
Participants

Fix Action

Fix / Workaround

B. Per-request schema patching

Code Example

client_id:
  - Authenticated end-user → hidden (auto-injected from session)
  - Admin/support user → visible (LLM asks the user which client to query)

debug_mode:
  - Productionhidden (always false)
  - Dev/staging → visible (LLM can toggle it)

---

class ConditionalParamMiddleware(ToolMiddleware):
    def process_schema(self, tool_name: str, schema: dict, context: dict) -> dict:
        if context.get("user_role") == "admin":
            return schema  # admin sees all params
        # Hide client_id for regular users
        schema["properties"].pop("client_id", None)
        return schema
RAW_BUFFERClick to expand / collapse

Feature Description

Follow-up from #20386 (tool I/O middleware).

Current state: partial_params on FunctionTool allows hiding parameters from the LLM tool schema and injecting values at call time. But this is all-or-nothing — a parameter is either always hidden or always visible, decided at tool creation time.

Feature request: Support conditionally hiding/showing tool parameters based on per-request runtime context.

Use case

client_id:
  - Authenticated end-user → hidden (auto-injected from session)
  - Admin/support user → visible (LLM asks the user which client to query)

debug_mode:
  - Production → hidden (always false)
  - Dev/staging → visible (LLM can toggle it)

In multi-tenant agent deployments, the same tool needs different schemas depending on who is making the request. Today you'd need to rebuild the entire tool list per request to change which fields are in partial_params — which means re-fetching from the MCP server and recreating the agent.

Why this is hard

fn_schema (the Pydantic model defining tool parameters) is frozen into each FunctionTool at creation time by McpToolSpec.to_tool_list_async(). The LLM sees this schema when deciding how to call the tool. To conditionally hide/show parameters per request, the schema itself would need to vary — which conflicts with the "create tools once at startup" pattern.

Possible approaches

A. Per-request tool list rebuilding

Rebuild the tool list per request with different partial_params depending on context.

  • Pro: Works with current API
  • Con: Re-fetches from MCP server every request, adds latency, requires agent rebuild

B. Per-request schema patching

A middleware hook (as proposed in #20386) that can modify fn_schema before the LLM sees it:

class ConditionalParamMiddleware(ToolMiddleware):
    def process_schema(self, tool_name: str, schema: dict, context: dict) -> dict:
        if context.get("user_role") == "admin":
            return schema  # admin sees all params
        # Hide client_id for regular users
        schema["properties"].pop("client_id", None)
        return schema
  • Pro: No MCP round-trip, reuses existing tools
  • Con: Mutating shared tool metadata is not thread-safe without per-request copies

C. Twin tools pattern

Register two versions of the same tool — one with the parameter visible, one hidden — and conditionally enable/disable them:

  • Pro: Clean, no schema mutation
  • Con: Duplicates tools, agent sees different tool sets per request

D. process_schema hook on the proposed ToolMiddleware

Extend the ToolMiddleware proposed in #20386 with a process_schema hook that runs before the schema is sent to the LLM, allowing per-request schema modification. This feels like the cleanest long-term solution.

Relationship to #20386

The process_input/process_output hooks proposed in #20386 solve the value injection side (deterministic overrides at call time). This issue is about the schema visibility side — controlling what the LLM sees it can provide, not just what values get injected.

A process_schema hook on ToolMiddleware would complete the picture:

  • process_schema → controls what the LLM sees (parameter visibility)
  • process_input → controls what values reach the tool (enforcement/injection)
  • process_output → controls what the agent sees (filtering/projection)

Reason

In production multi-tenant agent systems, the same MCP tools serve different user roles and environments. The tool's behavior doesn't change, but the interface presented to the LLM should adapt based on context — some parameters should be auto-injected (hidden) for regular users but explicitly provided (visible) for admin users.

Value of Feature

  • Enables multi-tenant agent deployments with role-based tool schemas
  • Avoids per-request MCP round-trips and agent rebuilds
  • Completes the middleware triad: schema visibility + input enforcement + output filtering

extent analysis

TL;DR

Implement a process_schema hook on the proposed ToolMiddleware to conditionally hide or show tool parameters based on per-request runtime context.

Guidance

  • Consider approach B. Per-request schema patching as a potential solution, which involves creating a middleware hook to modify the fn_schema before it is seen by the LLM.
  • Evaluate the trade-offs between the proposed approaches, including per-request tool list rebuilding, schema patching, twin tools pattern, and the process_schema hook on ToolMiddleware.
  • Assess the thread-safety implications of mutating shared tool metadata and consider using per-request copies to mitigate this risk.
  • Determine the feasibility of registering multiple versions of the same tool with different parameter visibility, as outlined in the twin tools pattern.

Example

class ConditionalParamMiddleware(ToolMiddleware):
    def process_schema(self, tool_name: str, schema: dict, context: dict) -> dict:
        if context.get("user_role") == "admin":
            return schema  # admin sees all params
        # Hide client_id for regular users
        schema["properties"].pop("client_id", None)
        return schema

Notes

The choice of approach depends on the specific requirements and constraints of the system, including performance, scalability, and maintainability considerations. The process_schema hook on ToolMiddleware appears to be a promising solution, but its implementation details and potential implications need to be carefully evaluated.

Recommendation

Apply workaround D. process_schema hook on the proposed ToolMiddleware, as it seems to be the most flexible and scalable solution, allowing for per-request schema modification without requiring significant changes to the existing tool infrastructure.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING