Working with Results
Once a task reaches succeeded, the answer and its sources are in the task object. This page covers how to read them and where the common pitfalls are. For the full field definitions, see The Task Object.
One result, three shapes
Section titled “One result, three shapes”| Field | Contents | When to use it |
|---|---|---|
answer |
The answer text (Markdown), identical to raw_result.rawContent |
When you only need the text |
raw_result |
The structured result: answer text, sources, execution steps, cards, timing, and more | Recommended for most use cases |
result_json |
The original result as a JSON string | For full archiving, or to read new fields raw_result doesn’t expose yet |
The three overlap, and each field can be up to 8 MiB, so task responses can be large. raw_result is only present once the task has a result (it succeeded, or the platform run failed). Queued, canceled, or dispatch-failed tasks don’t have this field, so check for it before reading.
How raw_result is encoded
Section titled “How raw_result is encoded”raw_result uses protobuf’s JSON encoding, which differs from the outer fields:
- Field names are camelCase:
rawContent,shareLink,agentSteps— whereas outer fields use snake_case likeshare_link. - Zero-value fields are omitted:
success: false,thinking: false, empty strings, empty arrays, and arankof 0 don’t appear. Fill in defaults when reading — in Python, for example,raw.get("references", []). elapsedMs(execution time in milliseconds, queueing excluded) is a string, such as"48213"; convert it to a number yourself.completedAtis a UTC timestamp in ISO 8601 format, such as2026-10-26T12:41:37.512Z.
Answer text
Section titled “Answer text”rawContent (and answer) is the platform’s original Markdown. The platform’s own citation markers and card placeholders are kept as-is, not converted.
On Global platforms (ChatGPT, Gemini, Claude, Perplexity, Copilot, Grok, Google AI Mode, Google AI Overview), the answer text is returned as the platform wrote it; no platform-specific marker conventions have been catalogued for them yet.
For China platforms, these are the markers we’ve observed:
| Platform | Markers in the answer text (examples) |
|---|---|
| DeepSeek | [citation:3]; [reference:3] with thinking mode on |
| Tencent Yuanbao | [citation:2]; card placeholders [](@replace=media_…) |
| Kimi | Citations wrapped in <REF>…</REF> |
| Zhipu ChatGLM | 【turn0search2】 |
| Metaso | [[2]]; images left in the text as Markdown images |
| ERNIE Bot | ^2^ (uncommon); may also appear as plain Markdown links |
| Qwen | Card placeholders such as [(video_note_list_1)] |
| Doubao, iFlytek Spark | Citation positions aren’t marked in the text |
| Xiaohongshu Diandian | Platform-native <u> underline tags, zero-width spaces, etc. |
Sources: references
Section titled “Sources: references”references lists every source the platform found or read for this answer, deduplicated by URL. Sources cited in the answer text come first, followed by those found but not cited. Each item:
| Field | Description |
|---|---|
rank |
Display order on the platform, starting at 1 |
title |
Title |
url |
Link; platform redirect links are resolved to the original URL where possible |
snippet |
Excerpt; may be empty |
source |
Source name (site name); may be empty |
domain |
Domain; may be empty |
contentPlatform |
The content platform detected (such as a particular content community); empty if not detected |
cited |
Whether the answer text cites it — three states, see below |
publishTime |
Publish time: ISO 8601, YYYY-MM-DD, or the platform’s relative wording (e.g. “1 day ago”); may be empty |
author |
Author (post author, video creator, etc.); may be empty |
The three states of cited
Section titled “The three states of cited”| Value | Meaning |
|---|---|
true |
The answer text cites this source |
false |
The platform found or read it, but the answer text doesn’t cite it |
| Field absent | The platform doesn’t distinguish cited vs. uncited — don’t treat this as false |
By platform (observed October 2026):
- Global platforms:
citedis not set. Every source arrives without the field. - Doubao, Kimi, Tencent Yuanbao, Zhipu ChatGLM, Metaso, ERNIE Bot: distinguish
true/false. - DeepSeek: sources it can tie to a specific web page are marked
true; sources it can only tie to a batch of search results are left unset. - iFlytek Spark: the platform currently doesn’t return search sources, so
referencesis built from links the model wrote into its answer.citedis alwaystrue, and there’s no information beyond the title. - Qwen and Xiaohongshu Diandian:
citedis not set.
Things to watch when reading
Section titled “Things to watch when reading”urlisn’t always a valid link. A few platforms have sources without a link (map plugins, for example), leavingurlempty; some return an internal platform ID instead. Check that it starts withhttp://orhttps://before using it.domaincan be empty. If you’re aggregating by domain anddomainis empty, parse it fromurl.- An empty
referenceslist is a normal result. Some questions don’t trigger a web search, so the answer has no sources.
Example: was your site cited?
Section titled “Example: was your site cited?”The code below finds sources from a given domain in the answer and splits them into “cited in the answer”, “found but not cited”, and “platform doesn’t distinguish”:
from urllib.parse import urlparse
def match_domain(ref, domain): host = ref.get("domain") or urlparse(ref.get("url", "")).hostname or "" return host == domain or host.endswith("." + domain)
def citation_report(task, domain): refs = (task.get("raw_result") or {}).get("references", []) hits = [r for r in refs if match_domain(r, domain)] return { "cited": [r for r in hits if r.get("cited") is True], "not_cited": [r for r in hits if r.get("cited") is False], "unknown": [r for r in hits if "cited" not in r], }
report = citation_report(task, "example.com")print({k: len(v) for k, v in report.items()})function matchDomain(ref, domain) { let host = ref.domain ?? ""; if (!host) { try { host = new URL(ref.url ?? "").hostname; } catch { host = ""; } } return host === domain || host.endsWith("." + domain);}
function citationReport(task, domain) { const hits = (task.raw_result?.references ?? []).filter((r) => matchDomain(r, domain)); return { cited: hits.filter((r) => r.cited === true), notCited: hits.filter((r) => r.cited === false), unknown: hits.filter((r) => r.cited === undefined), };}
const report = citationReport(task, "example.com");console.log(Object.fromEntries(Object.entries(report).map(([k, v]) => [k, v.length])));On Global platforms every hit lands in unknown, because they don’t set cited. There, “the platform used a page from your domain as a source” is the strongest signal available.
Execution steps: agentSteps
Section titled “Execution steps: agentSteps”Some platforms expose how they arrived at the answer, in order. Read the fields that match each step’s type:
type |
Fields to read | Contents |
|---|---|---|
thinking |
content, summary |
The reasoning text and the platform’s summary of it |
search |
name, queries, results |
The search queries the AI actually ran, and the results of each search (title, url, siteName, snippet) — not all of which are cited |
tool |
name, args |
Other tool calls and their raw arguments |
The queries of search steps are especially useful: they show what the AI actually searched for to answer the question, which can guide the keywords in your content. When a platform doesn’t expose its steps for a tier, agentSteps is absent. On Global platforms, agentSteps is currently usually absent.
thinking steps mostly appear only with thinking mode on; with it off, some China platforms such as Qwen, Zhipu ChatGLM, and Metaso may still include a short thinking or progress note. To tell whether an answer was produced with thinking on, check raw_result.thinking, not whether there are thinking steps.
Media cards: mediaCards
Section titled “Media cards: mediaCards”Video, image, product, and ranking cards in the answer, in the order they appear:
type:image,video,product,ranking, orother.anchor: the card’s placeholder text inrawContent, which tells you where the card sits. It’s empty when the platform doesn’t put placeholders in the text; then you can only go by order.items[]: each entry in the card, withtitle,url,imageUrl,source,author,duration,price,rating,publishTime, anddescription. Fields that weren’t captured are omitted.
On Global platforms, mediaCards is currently usually absent.
Share link
Section titled “Share link”share_link (raw_result.shareLink) is the platform’s share page for this conversation, letting someone review the original answer on the platform. It’s an empty string when the platform doesn’t provide one or creating the share failed; availability varies on Global platforms. Note that Xiaohongshu Diandian share links only open inside the Xiaohongshu app — they load as a blank page in a browser.
raw_result.conversationId and messageId are the platform’s own conversation and message IDs, for reference only. The API doesn’t support continuing a conversation from them.
Results of failed tasks
Section titled “Results of failed tasks”Tasks whose platform run failed (error_code is crawl_failed) also carry a raw_result. In it, success is absent (that is, false), rawContent is empty, and error holds the failure message (the same {"zh","en"} JSON string as error_message). To detect failure, check the outer status and error_code — see Error Handling.
