Knowledge Base-grounded Q&A. Streams the answer over SSE in three phases: planning, tool calling, and generation.
Overview
- Permissions: This API requires an Alibaba Cloud Model Studio API Key and a workspace. Obtain them on the API Key page and the Workspace Management page in the console.
- Call method: HTTP REST,
POST+application/json. The Base URL ishttps://{workspaceId}.cn-beijing.maas.aliyuncs.com, where{workspaceId}is the workspace ID. - Prerequisites: Create and publish a Knowledge Q&A service on the Knowledge Q&A service page in the console to obtain the application ID (
agent_id); otherwise an Agent-not-published error is reported. - Multi-turn context: The platform does not persist conversation state — pass the full
messageshistory on every request. Cap the history length (e.g. the last 10 turns) to stay within the model's context window. The response does not returnsession_id. - Streaming required:
streammust betrue; the current version supports only streaming responses. Passingfalseor leaving it empty fails the request. - In-chat files: After enabling in-chat file parsing in the console, you can pass files mid-conversation via
parameters.agent_options.session_files(up to 10). File IDs are obtained through the addFile endpoint. - Rate limit: 25 QPS per user by default. If throttled, retry later.
Request Syntax
Request Parameters
The request body consists of three parts: input, parameters, and stream. Nested fields are shown with their hierarchy in the table below.
Name | Type | Required | Description | Example |
|---|---|---|---|---|
input | object | Yes | Input parameters. | |
input.messages | array<object> | Yes | Conversation message list, in DashScope standard format. | |
messages[].role | string | Yes | Message role: | user |
messages[].content | string\|array | Yes | Message content. Either a plain-text string or a multimodal array of ContentPart (e.g. | |
input.request_id | string | No | Custom request ID set by the caller. | |
parameters | object | Yes | Configuration parameters. | |
parameters.agent_options | object | Yes | Agent-specific options, including | |
agent_options.agent_id | string | Yes | Q&A service (agent) application ID. Create and publish it on the Knowledge Q&A page in the console. | aid-xxxxxxxxxxxxxxxx |
agent_options.session_files | array<string> | No | Session file ID list, up to 10. Only takes effect after enabling in-chat file parsing in the console; file IDs are obtained via the | |
agent_options.enable_cache_control | boolean | No | Whether to enable explicit context caching (KV Cache). When | false |
stream | boolean | Yes | Whether to stream the output. Must be | true |
Response Parameters
Top-level fields
Name | Type | Description |
|---|---|---|
output | object | Model output. |
output.request_id | string | Custom request ID set by the caller (mirrors the request's |
output.choices | array<object> | Model output. Always length 1. See the table below for the structure. |
code | string | Status code; |
message | string | Status message; |
request_id | string | Request ID (DashScope platform-level; constant across the stream). |
usage | object | Token usage ( |
Name | Type | Description |
|---|---|---|
message | object | A single message, containing the model reply, tool call info, and the current phase. |
message.role | string | Role: |
message.content | string\|array | Generated content / tool return content. During |
message.id | string | Unique ID for this run (e.g. |
message.type | string | Message type: |
message.tool_calls | array<object> | Tool call info. Only present on |
message.tool_call_id | string | Tool return frame: matches |
message.additional_kwargs | object | Additional kwargs. |
message.extra | object | Step state info. See the table below. |
message.response_metadata | object | Model call details. Boundary frames carry |
finish_reason | string | Finish reason. |
Name | Type | Description |
|---|---|---|
group | string | Top-level phase: |
step | string | Current step: |
step_change | string | Step transition event: |
group | Description |
|---|---|
planning | Planning; includes start and end events. |
generating | Generating; includes start and end events. |
step | Description |
|---|---|
planning | Planning. |
tool_calling | Tool calling ( |
generating | Generating. |
step | step_change | Event | Description |
|---|---|---|---|
planning | plan_start | Plan start |
|
planning | empty | Planning |
|
planning | plan_end | Plan end |
|
tool_calling | tool_calling | Tool call | Emits the full |
tool_calling | tool_return | Tool return |
|
generating | generation_start | Generation start | Subsequent |
generating | empty | Generating |
|
generating | generation_end | Generation end |
|
tool_calls[].function.name. arguments is a JSON string — parse it once more to get the actual parameters. The tool result lives in the tool_return frame's additional_kwargs.extra_json.docs.
function.name | Tool | arguments | Returned docs[] |
|---|---|---|---|
semantic_search | Knowledge Base search | {"query", "target_ids"} | Matched chunk array with body and multi-dim scores. |
obtain_file | Fetch full file content | {"file_id", "max_tokens"} | File-level info (incl. Markdown presigned URL); full text in |
execute_sql | Run SQL query (NL2SQL) | {"sql", "knowledge_base_id"} | SQL result rows; each row = |
section_browse | Section browse | {"knowledge_base_id", "file_id", "section_path"} | Section preview (first 300 chars). |
section_peruse | Section peruse | {"knowledge_base_id", "file_id", "section_path", "max_tokens"} | Full section content. |
max_tokens (obtain_file / section_peruse) is a numeric string, e.g. "989482". target_ids / knowledge_base_id is the Knowledge Base (pipeline) ID; section_path separates levels with >, e.g. API Docs>Calling Conventions. Multiple tools can be chained in one request (e.g. semantic_search to locate a file → obtain_file for the full text).Context Caching
The Q&A pipeline is adapted for model-side context caching (KV Cache): the request prefix stays stable across multi-turn dialogue and multi-round tool calls, so cached input tokens are billed at a discounted rate and time-to-first-token drops. Two cache modes exist, and only one applies per request:
| Implicit cache | Explicit cache | |
|---|---|---|
| How to enable | On by default when the model supports it; no configuration needed and cannot be turned off | Pass enable_cache_control: true in the request |
| Hit determinism | Non-deterministic; the system auto-detects common prefixes | Deterministic — a matching prefix is a hit |
| Cache creation cost | 100% of input price (no extra charge) | 125% of input price |
| Cache hit price | 20% of input price | 10% of input price |
| TTL | Non-deterministic; cleaned up by the system periodically | 5 minutes, reset on every hit |
| Minimum cacheable length | 1024 tokens | 1024 tokens |
Enabling Explicit Caching
Add enable_cache_control under parameters.agent_options (default false); all other parameters stay unchanged:
Model Support
The two cache modes are supported on different model sets. The model is configured on the platform side — this endpoint exposes no model-selection parameter — so which cache mode is available depends on the model your Q&A service actually runs on:
| Model | Explicit cache | Implicit cache |
|---|---|---|
| qwen3.6-plus (current default) | Supported | Not supported |
| qwen3.6-flash | Supported | Not supported |
| qwen3.7-plus | Supported | Supported |
When to Use It
Cache gains fall into two categories — intra-request gains are more stable and more significant than cross-request ones.
Strongly recommended: multiple retrieval and reasoning rounds within one request. When one question triggers multiple tool-calling rounds (repeated semantic_search / execute_sql / section browsing plus intermediate reasoning), the cache breakpoint moves forward with each new tool result, and the previous round's full context (including retrieval results) becomes a stable prefix for the next. The more complex the question, the more retrieval rounds, and the longer the results, the greater the savings — unaffected by the 5-minute TTL or cross-request prefix drift.
Recommended: cross-request reuse:
| Scenario | Why |
|---|---|
| Multi-turn continuous dialogue | From the second turn on, the request hits the full history prefix of the previous turn; the longer the dialogue, the greater the gain |
| Long system prompt / large table schemas | Structured Knowledge Base schemas are stitched into the system prompt — large and stable within a session, ideal cache content |
| Repeated follow-ups on the same long document / session file | High share of stable prefix; create once, hit many times |
| Latency-sensitive workloads needing deterministic hits | Explicit caching is deterministic and unaffected by backend scheduling |
| Scenario | Why |
|---|---|
| One-shot single-turn short Q&A | Creates but never hits — you pay the 25% creation premium for nothing |
| Prefix shorter than 1024 tokens | Below the minimum cacheable length; nothing gets cached |
| Low-frequency calls spaced over 5 minutes apart | The explicit cache expires in 5 minutes; the next request re-creates it |
| Cross-request reuse in multimodal document scenarios | Image content blocks participate in prefix computation and easily diverge across requests; count only on intra-request gains |
| Switching Knowledge Bases / service configs every session | Different prefixes (schemas, KB info) cannot be reused |
enable_cache_control off doesn't fall back to implicit caching — it means no caching at all. If you still want some cache benefit in these scenarios, evaluate and enable it anyway.Observing Cache Hits
cached_tokens in the final frame's usage is the number of input tokens that hit the cache in this request:
cached_tokensis accumulated across the multiple model calls within the request;- The first request of a session always returns
cached_tokens: 0— it only creates the cache and has nothing to hit yet; this is expected; - From the second turn on,
cached_tokensshould be greater than 0 and grow with the dialogue history.
Notes and Limits
- The two cache modes are mutually exclusive:
enable_cache_control: truemeans explicit caching only, no implicit caching. On the default model qwen3.6-plus there is no implicit cache, so leaving it off means no cache — not a "fallback to implicit". - No hit on the first turn is normal: any cache must be created first;
cached_tokens=0doesn't indicate a malfunction. - 5-minute TTL for explicit cache: every hit resets it to 5 minutes; after a long pause, the next request re-creates the cache.
- Tool-definition changes invalidate the cache: tool definitions are part of the system prompt used in cache computation. For structured Knowledge Bases, carrying
search_filterssuppresses theexecute_sqltool — if filters come and go within one session, the tool list changes and the system prefix misses. Keepkb_search_configsstable within a session. - The prefix must be byte-for-byte stable: rebinding Knowledge Bases, changing service configs (e.g. custom instructions, the session-file switch), or a platform-side model change all alter the prefix and force cache re-creation.
- Cross-request hits are unstable in multimodal scenarios: with image input, image content blocks participate in prefix computation and easily diverge across requests; gains in such scenarios come mainly from intra-request multi-round retrieval — don't estimate by cross-request hits.
- Backtracking limit on very long turns: cache matching backtracks at most 20 content blocks from the breakpoint; extreme turns with many messages (multiple tool calls + image blocks) may exceed the range and miss.
- Caches are isolated by account and model: no sharing across accounts, or across models within one account.
input_tokens≠ created + hit: the backend appends a few tokens (usually under 10) after the prompt; they count toward total input but not toward cache statistics.
Verifying the Benefit
- Add
enable_cache_control: trueand run a complex question that triggers multi-round retrieval; check whether the final frame'scached_tokensis greater than 0; - Follow up 2-3 more turns in the same session (within 5 minutes); check whether
cached_tokensgrows with history and compare time-to-first-token; - A/B against the same request without the parameter (baseline should be
cached_tokens=0on the default model), then decide whether to keep it on based on "When to Use It".
Error Codes
In the SSE stream, errors are returned as event: error frames (the data: payload is an error JSON with code / message / request_id). Authentication failures are returned at the HTTP layer.
HTTP Status | Error Code | Description |
|---|---|---|
401 | InvalidApiKey | Authentication failed; the API Key is invalid or missing. |
500 | AgentApp.NotFound | The Agent does not exist or is not published, or another server-side error; returned as an SSE error frame. |
Examples
The following example asks the published Knowledge Q&A service "What is a Bailian Knowledge Base?"; replace agent_id with your actual Q&A service ID.