Skip to main content

Knowledge Chat

SSE-based Streaming Q&A grounded in your Knowledge Bases.

POST
/api/v2/apps/knowledge/chat
cURL
curl -X POST "https://{workspaceId}.cn-beijing.maas.aliyuncs.com/api/v2/apps/knowledge/chat" \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "input": {
      "messages": [
        {"role": "user", "content": [{"type": "text", "text": "What is a Bailian Knowledge Base?"}]}
      ]
    },
    "parameters": {
      "agent_options": {
        "agent_id": "aid-xxxxxxxxxxxxxxxx"
      }
    },
    "stream": true
  }'
{ "output": { "choices": [ { "message": { "role": "assistant", "type": "ai", "content": "A Bailian Knowledge Base is a knowledge management service on Alibaba Cloud Model Studio that supports document import, automatic chunking, semantic search, and Q&A.", "extra": { "step_change": "generation_start", "step": "generating", "group": "generating" }, "tool_calls": [] }, "finish_reason": "" } ], "request_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }, "code": "200", "message": "Success", "request_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }
Knowledge Base–grounded Q&A. The endpoint streams the answer over SSE in three phases: first planning (deciding what to search and which Knowledge Base), then tool calling (running the retrieval), then generation (producing the answer). Create and publish the Q&A service in the console first.
The response streams SSE events in this lifecycle: plan_start → plan_end → tool_calling → tool_return → generation_start → generation_end. The plan → tool_calling → tool_return segment can repeat multiple times (multi-round retrieval).

Basics

ItemValue
CallHTTP, SSE streaming output
EndpointPOST https://{workspaceId}.cn-beijing.maas.aliyuncs.com/api/v2/apps/knowledge/chat
Content-Typeapplication/json
Accepttext/event-stream recommended
AuthAuthorization: Bearer <API-Key>
Rate limitDefault 25 QPS per user

Execution phases

Phase (group)Description
planningPlanning; includes start and end events
generatingGenerating; includes start and end events
Step (step)Description
planningPlanning
tool_callingTool calling (group stays planning)
generatingGenerating
step_change may be absent due to the model — prefer the persistent step. On empty frames, step, step_change, and group may all be absent. A tool_call consists of two events: tool_calling (emits tool_calls) and tool_return (tool result).

Step transition events

stepstep_changeEventDescription
planningplan_startPlan startstep becomes planning; subsequent content is the planning text
planningemptyPlanningcontent is the planning text stream
planningplan_endPlan endstep is about to change; still planning at this event
tool_callingtool_callingTool callEmits full tool_calls (name + args); carries this round's usage
tool_callingtool_returnTool returnrole is tool; content is a summary; additional_kwargs.extra_json is the structured result (docs for retrieval)
generatinggeneration_startGeneration startSubsequent content is the answer text stream
generatingemptyGeneratingcontent is the answer text stream
generatinggeneration_endGeneration endfinish_reason is stop; carries the final usage

Event lifecycle

Tool catalog

During the tool-calling phase the model picks from the tools below; the tool name is in 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.nameToolargumentsReturn docs[]
semantic_searchKnowledge Base search{"query", "target_ids"}Matched chunk array with body and multi-dim scores
obtain_fileFetch full file content{"file_id", "max_tokens"}File-level info (incl. Markdown presigned URL); full text in message.content
execute_sqlRun SQL (NL2SQL){"sql", "knowledge_base_id"}SQL result rows; each row = _citation_index + query columns
section_browseSection browse{"knowledge_base_id", "file_id", "section_path"}Section preview (first 300 chars)
section_peruseSection 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 looks like API Docs>Calling conventions (>-separated levels).
  • Multiple tools can be chained in one request (e.g. semantic_search to locate a file → obtain_file for full text).

In-chat files (session_files)

After enabling in-chat file parsing in the console, you can pass a file mid-conversation. The file ID comes from the addFile (register file) endpoint. Full flow:
  1. Call applyFileUploadLease to get an upload lease and an OSS presigned URL
  2. PUT the file to OSS using the returned URL
  3. Call addFile to register the file and get a fileId
  4. Pass that fileId in this endpoint's parameters.agent_options.session_files (up to 10)
If in-chat file parsing is not enabled in the console, session_files is ignored.

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 cacheExplicit cache
How to enableOn by default when the model supports it; cannot be turned offPass enable_cache_control: true in the request
Hit determinismNon-deterministic; the system auto-detects common prefixesDeterministic — a matching prefix is a hit
Cache creation cost100% of input price (no extra charge)125% of input price
Cache hit price20% of input price10% of input price
TTLNon-deterministic; cleaned up by the system periodically5 minutes, reset on every hit
Minimum cacheable length1024 tokens1024 tokens
Pricing ratios and TTL are subject to the official Model Studio docs — Context Cache and Explicit Cache Best Practices — and your console bill. Internal benchmarks put the implicit-cache hit rate at roughly 75% of explicit caching; this is an empirical figure, not an official metric.

Enabling explicit caching

Add enable_cache_control under parameters.agent_options (default false); all other parameters stay unchanged:
curl -X POST "https://{workspaceId}.cn-beijing.maas.aliyuncs.com/api/v2/apps/knowledge/chat" \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "input": {
      "messages": [
        {"role": "user", "content": "What are the producing regions of these wines?"}
      ]
    },
    "parameters": {
      "agent_options": {
        "agent_id": "aid-xxxxxxxxxxxxxxxx",
        "enable_cache_control": true
      }
    },
    "stream": true
  }'

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:
ModelExplicit cacheImplicit cache
qwen3.6-plus (current default)SupportedNot supported
qwen3.6-flashSupportedNot supported
qwen3.7-plusSupportedSupported
The current default model qwen3.6-plus does not support implicit caching: without enable_cache_control, no cache is in effect at all and cached_tokens stays 0 — this is a model-side capability limit, not an endpoint defect. To gain cache benefits (lower cost + lower TTFT), turn on explicit caching. Only when the service runs on qwen3.7-plus does "implicit caching as a fallback" hold. For the model support list, refer to the "Supported models" section of the official explicit-cache doc.

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:
ScenarioWhy
Multi-turn continuous dialogueFrom 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 schemasStructured 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 fileHigh share of stable prefix; create once, hit many times
Latency-sensitive workloads needing deterministic hitsExplicit caching is deterministic and unaffected by backend scheduling
Break-even: explicit caching costs 25% extra on first write and saves 90% on every subsequent hit — one hit is enough to beat no caching at all. Not recommended (no gain, or even more expensive):
ScenarioWhy
One-shot single-turn short Q&ACreates but never hits — you pay the 25% creation premium for nothing
Prefix shorter than 1024 tokensBelow the minimum cacheable length; nothing gets cached
Low-frequency calls spaced over 5 minutes apartThe explicit cache expires in 5 minutes; the next request re-creates it
Cross-request reuse in multimodal document scenariosImage content blocks participate in prefix computation and easily diverge across requests; count only on intra-request gains
Switching Knowledge Bases / service configs every sessionDifferent prefixes (schemas, KB info) cannot be reused
"Not recommended" only means explicit caching doesn't pay off there. Because the default model qwen3.6-plus doesn't support implicit caching, leaving 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:
{
  "usage": {
    "input_tokens": 12345,
    "output_tokens": 678,
    "total_tokens": 13023,
    "cached_tokens": 9800
  }
}
  • cached_tokens is 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_tokens should be greater than 0 and grow with the dialogue history;
  • You can also check the cache_tokens metric under "Model Monitoring" in the Model Studio console, or filter by cache in "Billing Details".

Notes and limits

  1. The two cache modes are mutually exclusive: enable_cache_control: true means 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".
  2. No hit on the first turn is normal: any cache must be created first; cached_tokens=0 doesn't indicate a malfunction.
  3. 5-minute TTL for explicit cache: every hit resets it to 5 minutes; after a long pause, the next request re-creates the cache.
  4. Tool-definition changes invalidate the cache: tool definitions are part of the system prompt used in cache computation. For structured Knowledge Bases, carrying search_filters suppresses the execute_sql tool — if filters come and go within one session, the tool list changes and the system prefix misses. Keep kb_search_configs stable within a session.
  5. 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.
  6. 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.
  7. 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.
  8. Caches are isolated by account and model: no sharing across accounts, or across models within one account.
  9. 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

  1. Add enable_cache_control: true and run a complex question that triggers multi-round retrieval; check whether the final frame's cached_tokens is greater than 0;
  2. Follow up 2-3 more turns in the same session (within 5 minutes); check whether cached_tokens grows with history and compare time-to-first-token;
  3. A/B against the same request without the parameter (baseline should be cached_tokens=0 on the default model), then decide whether to keep it on based on "When to use it".

Client assembly guide

GoalHow
Planning textAccumulate message.content across all step == "planning" frames
Final answerAccumulate message.content across all step == "generating" frames
CitationsTake from tool_return's additional_kwargs.extra_json.docs, mapped by _citation_index
UsageTake top-level usage from the generation_end frame (answer usage); retrieval usage is on the corresponding tool_calling frame

Multi-turn dialogue

The platform doesn't persist conversation state — pass the full messages history on every request. Cap history length (around the last 10 turns) to stay within the model's context window.

Authorizations

string
header
required

DashScope API Key, obtained from the API Key page in the console.

Body

application/json
object
required

Input parameters.

object
required

Configuration parameters.

boolean
defaulttrue
required

Whether to stream the output. Must be true — the current version supports only streaming; passing false or omitting it fails the request.

Response

200-text/event-stream
object
string

Status code. 200 on success.

string

Status message. Success on success.

string

Request ID (DashScope platform-level; constant across the stream).

object