perplexity/kimi-k3.
Kimi K3 researches the topic with live web_search, reasons across the evidence, and hand-codes a self-contained HTML page with animated statistics, inline SVG charts, narrative, and citations. The CLI makes the long-running job durable, validates the page, and inserts source URLs from structured API results rather than trusting URLs written by the model.
Features
- One submitted Agent API job handles research, synthesis, data visualization, and front-end implementation
- Live
web_searchgrounds the draft in current source material - Kimi K3 builds all HTML, CSS, JavaScript, and SVG without a chart library
- Durable background mode saves the response ID immediately and polls the same run under a real local deadline without resubmitting the paid request
quickandshowcaseprofiles balance latency, cost, and polish- Every statistic and plotted value must reference a numeric API search-result ID before the artifact can be saved
- Canonical titles, dates, and URLs are injected from API metadata
- Self-contained output works offline and receives a restrictive Content Security Policy
- A sanitized JSON receipt records request settings, model, response ID, searches, sources, usage, cumulative client latency, per-attempt history, and provider-reported cost
- The development test suite exercises the pinned SDK serializer and recovery path without network calls; this standalone page embeds that exact verified script
Prerequisites
- Python 3.10 or newer (tested with Python 3.12)
- A Perplexity API key
- Internet access for live Agent API runs
Installation
This is a self-contained tutorial. Copy the complete Python block under Full Code into a local file nameddata_story.py, then create an isolated environment and install the exact SDK version used for verification:
API Key Setup
Set the key only in your environment; do not paste it into the script or commit it to source control.PERPLEXITY_API_KEY automatically.
Quick Start
After saving the Full Code block asdata_story.py, create a story with the default quick profile:
Usage
--receipt path when resuming to preserve the original request, archive earlier client errors with their attempt, and append resume history. The receipt distinguishes total client time from the most recent attempt and, for a newly submitted run, records the time spent reaching provider completion. The default receipt path is <output>.receipt.json.
Configuration Reference
Override any profile value directly:
max_output_tokens is an explicit ceiling, not a required reservation or a prediction of actual output. Billing follows the work the run actually performs; consult current pricing before high-budget runs.
All documented K3 effort values are preserved. In perplexityai==0.43.1, the generated type omits max, so the script sends only that value through the SDK’s supported extra_body pass-through. Other effort levels use the typed reasoning field.
Dry Run Request Preview
--dry-run is deterministic and does not use an API key or spend credits. An abridged request preview looks like this:
verified source links means that each used source ID and URL matched structured API results; it does not mean the cited claim was fact-checked. The receipt retains the raw provider value. If the provider omits cost data, the CLI reports unavailable rather than displaying a false $0.0000. client_elapsed_seconds is cumulative across recorded attempts; last_client_attempt_elapsed_seconds identifies a fast resume/finalization pass without misrepresenting it as full generation latency.
Example Output (truncated)
On a successful run, terminal output has this shape. This is an illustrative format example; query count, latency, linked sources, and cost vary by topic and run.Observed Live Execution
The exact script embedded below was exercised against the live Agent API on August 7, 2026 UTC (August 6 in US Pacific time). One paid backgroundPOST was submitted, automatic create retries were disabled, and the same response ID was polled to completion.
The structural and browser checks passed: four statistic cards, three SVG charts, seven focusable data marks, canonical source injection, no external assets or background requests, no console warnings or errors, no horizontal overflow at 1,440px or 390px, and no API-key leakage.
The generated page still failed publication-level editorial review. Its date chip omitted earlier plotted years, one chart presented a period average as a late-period endpoint, one sentence claimed that every major US lab shipped open weights, one sentence changed a download-share finding into a model-count claim, and the generated wrapper produced two visible Sources headings. These findings are intentionally reported here: API completion and structural grounding produce an inspectable draft, not an automatic fact-check or publication guarantee.
This record proves that the Agent API request completed and the CLI saved an artifact. It does not certify factual accuracy, chart interpretation, accessibility, or publication readiness.Latency, search work, token use, and cost vary by topic and run. This observed receipt is evidence that the workflow executed successfully, not a benchmark or pricing promise.
Code Walkthrough
- The CLI builds one Agent API request with
web_search, a K3 effort level, an output ceiling, and a maximum number of agent steps. - It submits once with
background=Trueandstore=True, with automatic retries disabled for the create call. - The background create response returns an ID immediately; the CLI writes it to the receipt before doing anything else.
- The CLI polls
client.responses.retrieve(response_id)with bounded request timeouts and explicit backoff. Status changes and newly visible search queries are printed without holding a long-lived stream open. - K3 labels every statistic card and SVG data mark with a numeric result ID and leaves one
PERPLEXITY_SOURCESplaceholder. - On completion, the CLI validates the document, rejects clipped chart marks and reduced-motion-unsafe SVG animation, matches every used ID against
response.outputsearch results, injects authoritative source links and a Content Security Policy, then writes the HTML atomically.
completed. Pending statuses are queued and in_progress; every other status is treated as a terminal non-success so schema drift cannot create an infinite polling loop.
If the create connection fails before any response ID arrives, the submission outcome is ambiguous. The CLI records submission_unknown and deliberately does not retry. Check your API activity before deciding whether to submit again.
Source-link contract
K3 never needs to reproduce external URLs. The prompt requires citation fragments such as#source-3 and data-source-id="3"; the CLI inserts the URL for result 3 from the API’s structured search_results output.
The validator rejects incomplete documents, unknown source IDs, model-written external URLs, remote assets, frames, active forms, network-capable JavaScript, conflicting source mappings, non-focusable chart marks, SVG SMIL animation, and simple mark geometry outside a chart’s viewBox. It also rejects global svg { width: 100% } rules that can accidentally turn small interface icons into page-sized graphics. This proves structural source linkage and catches common rendering failures, not semantic entailment or every possible scale error: a human must still verify that the prose and chart geometry correctly interpret each source.
Prompting Guidance
- Keep research and artifact construction in one explicit two-phase prompt so K3 can connect source IDs to the HTML it writes.
- Ask for exact source terminology and prohibit inferred scope or rhetorical comparisons. A citation can exist while the surrounding claim still overstates what the source establishes.
- Specify the chart contract mechanically: numeric
data-source-id, matching citation, focusable simple geometry, a shared axis scale, visible bounds, and a tooltip for every mark. - Require CSS-only animation plus a reduced-motion media query. SVG SMIL animation is deliberately rejected because CSS cannot reliably disable it.
- Scope responsive sizing to
figure svg; never apply chart dimensions to every SVG on the page. - Treat output as a draft. The validator checks structure, provenance wiring, and common rendering failures; editorial and numeric review remain required.
Full Code
Save this complete block asdata_story.py. It is byte-for-byte identical to the implementation used for the offline verification and live paid run reported above.
Offline Verification
After saving the Full Code block asdata_story.py, these checks make no network request and spend no API credits:
high and max SDK serialization, one-POST background execution, timeouts, terminal states, --resume, cost handling, source injection, CSP insertion, chart bounds, reduced motion, unsafe markup, receipt accounting, secret redaction, and README/source synchronization.
Limitations
- The generated page is a draft. Structural citation checks cannot determine whether a sentence misreads, overstates, or omits context from its source.
- Simple SVG marks are checked against the
viewBox, but a coordinate can still be internally inconsistent with an axis while remaining in bounds. Verify the plotted scale and every label before publication. - Verify SVG label size at mobile widths. A chart can avoid horizontal overflow and still make text too small to read.
- Search quality depends on current coverage. Sparse or conflicting results may cause validation to fail, in which case no HTML is published.
- High-effort research and full-page generation can take many minutes. Use the response ID and
--resume; do not blindly submit duplicates. - The output contract is one self-contained HTML page. Multi-page projects need a different artifact workflow.
- A browser-level visual audit is still recommended before publishing to check layout, tooltips, accessibility, and mobile behavior.
- Run receipts never contain the API key, but the topic and source snippets may still be sensitive and should be reviewed before sharing.