QVeris
运行任务
文档目录

QVeris 文档

什么是 QVeris

QVeris面向智能体的能力路由网络。它让你的智能体能够:

  • 发现(Discover) 能力(API、数据源、自动化任务),使用自然语言描述需求 — 免费
  • 检查(Inspect) 候选能力,比较参数、成功率、延迟和价格
  • 调用(Call) 任意能力,传入结构化参数,获取结构化结果

QVeris 在智能体循环中表现出色(发现 → 检查 → 调用 → 将结果反馈给模型),支持多种集成方式。

进行 Provider 比较时,如果需要确认当前范围或完整契约,必须逐一 Inspect;Discover 摘要不等于确认。比较需要当前报价时,必须逐一 Probe。复用只能保留精确路由,不能保留业务参数或结果:参数必须来自当前请求;当前、最新、今天或其他时效性数据必须执行新的 Call。

费用: 发现(Discover)免费。调用(Call)按能力的计费规则定价,最终结算结果可在调用历史和积分账本中查看。注册验证后可一次性获得 1,000 体验积分。详情见定价页面


快速开始

QVeris 提供多种使用方式,选择最适合你的即可。

使用 QVeris CLI

在终端中直接发现、检查和调用能力。

安装

bash
curl -fsSL https://qveris.ai/cli/install | bash

也可通过 npm 安装(npm install -g @qverisai/cli)或免安装运行(npx @qverisai/cli)。

快速上手

bash
qveris login                              # 登录认证
qveris discover "天气预报"                # 发现能力
qveris inspect 1                          # 查看详情
qveris call 1 --params '{"wfo":"LWX","x":90,"y":90}'  # 调用执行

CLI 还支持交互模式(qveris interactive)、代码生成(--codegen curl|python|js)和 Shell 自动补全。完整参考见 CLI 文档


通过 MCP 使用 QVeris

如果你的客户端支持 Model Context Protocol (MCP) 和远程 Streamable HTTP,应优先使用托管 MCP。它无需本地软件包或 Node.js 进程,立即获得:

  • discover(发现)
  • inspect(检查)
  • call(调用)

完整 MCP 参考文档见 MCP 服务器文档托管 MCP 指南

托管 MCP 配置(首选)

json
{
  "mcpServers": {
    "qveris": {
      "type": "http",
      "url": "https://mcp.qveris.ai/mcp",
      "headers": {
        "Authorization": "Bearer your-api-key-here"
      }
    }
  }
}

本地 stdio 备用方案(仅适用于不支持远程 HTTP 的客户端)

json
{
  "mcpServers": {
    "qveris": {
      "command": "npx",
      "args": ["-y", "@qverisai/mcp"],
      "env": {
        "QVERIS_API_KEY": "your-api-key-here"
      }
    }
  }
}

试一试

"发现一个天气能力,获取东京的实时天气"

助手会:

  • 调用 discover 发现匹配的能力(如"天气")
  • 可选调用 inspect 检查最佳候选
  • 使用能力 ID 和参数调用 call

使用 QVeris Python SDK

Python SDK 现在位于本单体仓库的 packages/python-sdk。安装已发布的包:

bash
pip install qveris

完整指南(client、agent、类型化模型、集成方式)见 Python SDK

设置环境变量:

  • QVERIS_API_KEY(在控制台/API密钥中创建)
  • OPENAI_API_KEY(或你的 OpenAI 兼容服务商密钥)
  • OPENAI_BASE_URL(可选;用于 OpenAI 兼容服务商)

Typed client 工作流:

python
import asyncio
import math
from qveris import QverisClient

def matches_type(kind, value):
    return {
        "string": lambda: isinstance(value, str),
        "integer": lambda: isinstance(value, int) and not isinstance(value, bool),
        "number": lambda: isinstance(value, (int, float)) and not isinstance(value, bool) and math.isfinite(value),
        "boolean": lambda: isinstance(value, bool),
        "array": lambda: isinstance(value, list),
        "object": lambda: isinstance(value, dict),
    }.get(kind, lambda: False)()

def supports_request(candidate, params):
    if candidate.params is None:
        return False
    definitions = {p.name: p for p in candidate.params}
    if len(definitions) != len(candidate.params):
        return False
    return all(not p.required or p.name in params for p in candidate.params) and all(
        (p := definitions.get(name)) is not None and matches_type(p.type, value)
        and (p.enum is None or any(allowed == value and
             isinstance(allowed, bool) == isinstance(value, bool) for allowed in p.enum))
        for name, value in params.items()
    )

async def main():
    client = QverisClient()
    try:
        discovered = await client.discover("weather forecast API", limit=5)
        params = {"city": "北京"}
        selected = next(
            (
                candidate
                for candidate in discovered.results
                if supports_request(candidate, params)
            ),
            None,
        )
        if selected is None:
            inspected = await client.inspect(
                [candidate.tool_id for candidate in discovered.results[:3]],
                search_id=discovered.search_id,
            )
            selected = next(
                (
                    candidate
                    for candidate in inspected.results
                    if supports_request(candidate, params)
                ),
                None,
            )
        if selected is None:
            raise RuntimeError("没有候选能力提供兼容的当前参数契约")
        result = await client.call(
            selected.tool_id,
            params,
            search_id=discovered.search_id,
        )
        print(result.execution_id, result.success, result.billing)
    finally:
        await client.close()

asyncio.run(main())

最小流式示例:

python
import asyncio
from qveris import Agent, Message

async def main():
    agent = Agent()
    messages = [Message(role="user", content="发现一个天气能力,查询纽约的实时天气。")]
    async for event in agent.run(messages):
        if event.type == "content" and event.content:
            print(event.content, end="", flush=True)

if __name__ == "__main__":
    asyncio.run(main())

使用 QVeris TypeScript SDK

TypeScript/JavaScript SDK 位于本单体仓库的 packages/js-sdk。安装已发布的包:

bash
npm install @qverisai/sdk

这是一个零依赖的类型化客户端(原生 fetch,Node.js 18+)。完整指南(配置、API 参考、类型化响应、错误处理)见 TypeScript SDK

typescript
import { Qveris } from '@qverisai/sdk';

const qveris = Qveris.fromEnv(); // 读取 QVERIS_API_KEY

const discovered = await qveris.discover('weather forecast API', { limit: 5 });
const parameters: Record<string, unknown> = { city: 'London' };
const matchesType = (type: string, value: unknown) => {
  if (type === 'string') return typeof value === 'string';
  if (type === 'integer') return typeof value === 'number' && Number.isFinite(value) && Number.isInteger(value);
  if (type === 'number') return typeof value === 'number' && Number.isFinite(value);
  if (type === 'boolean') return typeof value === 'boolean';
  if (type === 'array') return Array.isArray(value);
  if (type === 'object') return value !== null && typeof value === 'object' && !Array.isArray(value);
  return false;
};
const supportsRequest = (candidate: (typeof discovered.results)[number]) => {
  if (!candidate.params) return false;
  const definitions = new Map(candidate.params.map((parameter) => [parameter.name, parameter]));
  if (definitions.size !== candidate.params.length) return false;
  return Object.entries(parameters).every(([name, value]) => {
    const parameter = definitions.get(name);
    return Boolean(parameter && matchesType(parameter.type, value) &&
      (!parameter.enum || parameter.enum.some((allowed) => Object.is(allowed, value))));
  }) &&
    candidate.params.every((parameter) =>
      !parameter.required || Object.prototype.hasOwnProperty.call(parameters, parameter.name),
    );
};
let tool = discovered.results.find(supportsRequest);
if (!tool) {
  const inspected = await qveris.inspect(
    discovered.results.slice(0, 3).map((candidate) => candidate.tool_id),
    { searchId: discovered.search_id },
  );
  tool = inspected.results.find(supportsRequest);
}
if (!tool) throw new Error('没有候选能力提供包含 city 字段的当前契约。');
const result = await qveris.call(tool.tool_id, {
  parameters,
  searchId: discovered.search_id,
});
console.log(result.execution_id, result.success, result.billing);

直接调用 QVeris REST API

基础 URL

https://qveris.ai/api/v1

身份认证

Authorization 请求头中携带 API 密钥:

text
Authorization: Bearer YOUR_API_KEY

1)发现能力

POST /search

cURL

bash
curl -sS -X POST "https://qveris.ai/api/v1/search" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"query\":\"天气预报 API\",\"limit\":10}"

响应包含 search_id 和能力列表(每项含 tool_id、参数结构、示例等)。

Python

python
import os
import requests

API_KEY = os.environ["QVERIS_API_KEY"]

resp = requests.post(
    "https://qveris.ai/api/v1/search",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={"query": "天气预报 API", "limit": 10},
    timeout=30,
)
resp.raise_for_status()
data = resp.json()
print(data["search_id"])
print(data["results"][0]["tool_id"] if data.get("results") else None)

TypeScript

typescript
const apiKey = process.env.QVERIS_API_KEY!;

const resp = await fetch("https://qveris.ai/api/v1/search", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ query: "天气预报 API", limit: 10 }),
});

if (!resp.ok) throw new Error(`HTTP ${resp.status}: ${await resp.text()}`);
const data = await resp.json();
console.log(data.search_id);
console.log(data.results?.[0]?.tool_id);

2)检查能力

POST /tools/by-ids

调用之前,可以检查一个或多个能力,查看完整详情(参数、成功率、延迟等)。

cURL

bash
curl -sS -X POST "https://qveris.ai/api/v1/tools/by-ids" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"tool_ids\":[\"openweathermap.weather.execute.v1\"],\"search_id\":\"YOUR_SEARCH_ID\"}"

Python

python
resp = requests.post(
    "https://qveris.ai/api/v1/tools/by-ids",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "tool_ids": ["openweathermap.weather.execute.v1"],
        "search_id": "YOUR_SEARCH_ID",
    },
    timeout=30,
)
resp.raise_for_status()
print(resp.json())

TypeScript

typescript
const resp = await fetch("https://qveris.ai/api/v1/tools/by-ids", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    tool_ids: ["openweathermap.weather.execute.v1"],
    search_id: "YOUR_SEARCH_ID",
  }),
});

if (!resp.ok) throw new Error(`HTTP ${resp.status}: ${await resp.text()}`);
const data = await resp.json();
console.log(data.results);

返回与 /search 相同的结构 — 包含完整能力详情、参数、示例和统计数据。

3)调用能力

POST /tools/execute?tool_id={tool_id}

cURL(调用发现阶段返回的能力)

bash
curl -sS -X POST "https://qveris.ai/api/v1/tools/execute?tool_id=openweathermap.weather.execute.v1" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"search_id\":\"YOUR_SEARCH_ID\",\"parameters\":{\"city\":\"London\",\"units\":\"metric\"},\"max_response_size\":20480}"

若输出超过 max_response_size,响应会包含 truncated_content 和临时的 full_content_file_url

Python

python
import os
import requests

API_KEY = os.environ["QVERIS_API_KEY"]

tool_id = "openweathermap.weather.execute.v1"  # 来自发现结果
search_id = "YOUR_SEARCH_ID"  # 来自 /search 响应

resp = requests.post(
    f"https://qveris.ai/api/v1/tools/execute?tool_id={tool_id}",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "search_id": search_id,
        "parameters": {"city": "北京", "units": "metric"},
        "max_response_size": 20480,
    },
    timeout=60,
)
resp.raise_for_status()
print(resp.json())

TypeScript

typescript
const apiKey = process.env.QVERIS_API_KEY!;

const toolId = "openweathermap.weather.execute.v1"; // 来自发现结果
const searchId = "YOUR_SEARCH_ID"; // 来自 /search 响应

const resp = await fetch(
  `https://qveris.ai/api/v1/tools/execute?tool_id=${encodeURIComponent(toolId)}`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      search_id: searchId,
      parameters: { city: "London", units: "metric" },
      max_response_size: 20480,
    }),
  }
);

if (!resp.ok) throw new Error(`HTTP ${resp.status}: ${await resp.text()}`);
const data = await resp.json();
console.log(data);

在 AI 智能体中安装 QVeris

如果你正在配置 AI 编程助手或桌面端智能体(ChatGPT(Codex)、Claude Code、Cursor、GitHub Copilot、Cline、Roo Code、Continue、Kiro、Junie、Augment、Zed、Google Antigravity、Qoder、CodeBuddy、WorkBuddy、OpenCode、TRAE 等),可以将 智能体安装指南 连同你的 API 密钥一起提供给智能体。它会自动检测运行环境,并完成可用 MCP 服务器和技能定义的配置。

支持 MCP 的桌面端客户端包括:ChatGPT(Codex)、Claude Desktop、Cursor、GitHub Copilot、Cherry Studio、Cline、Roo Code、Continue、Kiro、Junie、Augment、Zed、Google Antigravity、Qoder、CodeBuddy、WorkBuddy、OpenCode、TRAE、Windsurf 和 VS Code。


如何获取 API 密钥

  1. 打开控制台/API密钥
  2. 登录 / 注册账号(免费,注册验证后一次性获得 1,000 体验积分)
  3. 创建 API 密钥
  4. 使用方式:
    • QVERIS_API_KEY 环境变量(MCP / Python SDK),或
    • Authorization: Bearer ... 请求头(REST API)

推荐系统提示词

在启用 QVeris 工具时,将以下内容复制粘贴到助手的系统提示词中:

text
你是一个有用的助手,可以动态发现并调用各种能力来帮助用户。首先思考完成用户任务可能需要哪类能力。然后使用 discover 工具,以描述能力的查询词进行搜索,而非直接写出你稍后要传入的具体参数。再使用 call 工具调用合适的能力,通过 params_to_tool 传入参数。如果能力具有 success_rate 和 avg_execution_time,请在选择时加以参考。你可以参考每个能力提供的示例。你可以在一次响应中发起多个工具调用。

开放生态

QVeris 的核心引擎是托管服务。所有客户端工具(MCP 服务器、SDK、技能、插件)均为开源:

这个页面对你有帮助吗?