You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Llama Index ReActAgent无法同时使用两个Tool Spec问题求助

问题:Llama Index ReActAgent同时启用OpenAPIToolSpec与RequestsToolSpec时忽略前者的解决方案

问题概况

  • 单独使用OpenAPIToolSpec时,查询"获取列出我的公司的完整API调用"可返回正确接口地址;
  • 单独使用RequestsToolSpec时,调用指定API可返回正确公司数据;
  • 同时启用两个Tool Spec时,Agent跳过load_openapi_spec调用,直接使用RequestsToolSpec的默认配置发起请求导致失败;
  • Agent能正常列出所有工具,自定义简单工具可协同工作,多次调整系统提示未生效。

相关代码示例

import asyncio
import logging
import os

from dotenv import load_dotenv
from llama_index.core.agent import ReActAgent
from llama_index.core.agent.workflow import AgentStream
from llama_index.core.workflow import Context
from llama_index.llms.bedrock_converse import BedrockConverse
from llama_index.tools.openapi import OpenAPIToolSpec
from llama_index.tools.requests.base import RequestsToolSpec

load_dotenv()

logger = logging.getLogger('my-agent')
logging.basicConfig(level=logging.INFO)

model_id = os.getenv("FOUNDATION_MODEL")
aws_region = os.getenv("AWS_REGION")

llm = BedrockConverse(
    model=model_id,
    region_name=aws_region,
    max_tokens=10000,
    temperature=0.1
)

openapi_tool = OpenAPIToolSpec(
    url=os.getenv("API_ENDPOINT") + "/openapi.json",
)

requests_tool = RequestsToolSpec(
    domain_headers={
        os.getenv("API_DOMAIN"): {
            "Authorization": f"Bearer {os.getenv('ACCESS_TOKEN')}",
            "Content-Type": "application/json",
        }
    }
)

system_prompt = """
You are an agent with two tools: load_openapi_spec and post_request.
- FIRST, use load_openapi_spec to select the correct API endpoint and parameters from the provided OpenAPI specification based on the user's query.
- SECOND, use post_request to make the HTTP request to the selected endpoint with the appropriate method and parameters.
"""

agent = ReActAgent(
    tools=openapi_tool.to_tool_list() + requests_tool.to_tool_list(['post_request']),
    llm=llm,
    verbose=True,
    system_prompt=system_prompt
)

ctx = Context(agent)


async def main(user_message: str):
    handler = agent.run(user_message, ctx=ctx)
    buffer = ""

    async for ev in handler.stream_events():
        if isinstance(ev, AgentStream):
            buffer += ev.delta

            if '\n' in buffer:
                lines = buffer.split('\n')
                for line in lines[:-1]:
                    logger.info(line)
                buffer = lines[-1]

    response = await handler
    logger.info(f"Final response: {response}")

prompt = "<My prompt here...>"
asyncio.run(main(prompt))

错误响应示例

INFO:my-agent:Action Input: {"url_template": "https://api.example.com/api/companies", "body": {}}Thought: ```
INFO:my-agent:Thought: The current language of the user is: English. I cannot answer the question with the provided tools.
INFO:my-agent:Answer: I cannot list your companies because the API endpoint provided is not valid. Please provide a valid API endpoint.
INFO:my-agent:Final response: I cannot list your companies because the API endpoint provided is not valid. Please provide a valid API endpoint.

自定义工具协同正常示例

def multiply(a: int, b: int) -> int:
    """Multiply two integers and returns the result integer"""
    return a * b


def add(a: int, b: int) -> int:
    """Add two integers and returns the result integer"""
    return a + b

agent = ReActAgent(tools=[multiply, add], llm=llm)

解决方案建议

1. 强化工具描述,引导LLM优先选择

给OpenAPIToolSpec的工具添加明确的强制指令描述,让LLM清晰认知调用顺序:

openapi_tools = openapi_tool.to_tool_list()
# 给load_openapi_spec工具添加强约束描述
for tool in openapi_tools:
    if tool.metadata.name == "load_openapi_spec":
        tool.metadata.description = "【必须优先调用】加载OpenAPI规范,获取与用户查询匹配的正确API端点、请求方法和参数,只有调用此工具后,才能使用post_request发起请求"

requests_tools = requests_tool.to_tool_list(['post_request'])
# 给post_request添加依赖提示
for tool in requests_tools:
    tool.metadata.description = "必须在调用load_openapi_spec获取有效API信息后,才能使用此工具发送HTTP请求"

# 重新初始化agent
agent = ReActAgent(
    tools=openapi_tools + requests_tools,
    llm=llm,
    verbose=True,
    system_prompt=system_prompt
)

2. 自定义工具检索逻辑,强制优先级

通过tool_retriever指定工具选择顺序,确保load_openapi_spec被优先考虑:

from llama_index.core.tools import FixedToolRetriever

# 先获取openapi工具,再获取requests工具
all_tools = openapi_tool.to_tool_list() + requests_tool.to_tool_list(['post_request'])
# 创建固定顺序的工具检索器,优先返回openapi工具
tool_retriever = FixedToolRetriever(tools=all_tools)

agent = ReActAgent(
    tools=all_tools,
    llm=llm,
    verbose=True,
    system_prompt=system_prompt,
    tool_retriever=tool_retriever
)

3. 封装复合工具,强制执行流程

将两个工具的逻辑封装成一个复合工具,确保先执行load_openapi_spec再发起请求:

from llama_index.core.tools import FunctionTool
import json

async def fetch_companies():
    # 获取load_openapi_spec工具并调用
    load_spec_tool = next(t for t in openapi_tool.to_tool_list() if t.metadata.name == "load_openapi_spec")
    spec_result = await load_spec_tool.call()
    
    # 解析OpenAPI规范,提取列出公司的接口信息
    spec_data = json.loads(spec_result)
    # 假设从spec中提取到正确的POST端点
    endpoint = spec_data["paths"]["/api/companies"]["post"]["url"]
    
    # 获取post_request工具并调用
    post_tool = next(t for t in requests_tool.to_tool_list(['post_request']) if t.metadata.name == "post_request")
    request_result = await post_tool.call(url_template=endpoint, body={})
    
    return request_result

# 创建复合工具
fetch_companies_tool = FunctionTool.from_defaults(fn=fetch_companies, name="fetch_companies", description="获取公司列表,自动先加载OpenAPI规范再发起请求")

# 用复合工具初始化agent
agent = ReActAgent(
    tools=[fetch_companies_tool],
    llm=llm,
    verbose=True
)

4. 优化系统提示,增强指令约束

修改系统提示为更具强制性的措辞:

system_prompt = """
你必须严格遵循以下步骤处理用户请求:
1. 第一步:调用load_openapi_spec工具,加载并解析OpenAPI规范,从中找到与用户查询匹配的API端点、请求方法和参数。
2. 第二步:基于第一步获取的信息,调用post_request工具发起HTTP请求。
绝对不能跳过第一步直接调用post_request,否则请求会失败。
"""

5. 降低LLM温度,增强指令遵循性

将temperature调整为0,让LLM更严格执行指令:

llm = BedrockConverse(
    model=model_id,
    region_name=aws_region,
    max_tokens=10000,
    temperature=0  # 从0.1改为0
)

内容的提问来源于stack exchange,提问作者UserX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 11:14:53