agentsclimarketplace

Use whispers

Skill southwind-ai/use-whispers/skills/use-whispers

Guide for building products and integrations on top of Southwind Whispers — an AI-powered analytics and report generation platform. Covers domain concepts (data origins, data sources, reports, agents), API key authentication, and end-to-end developer workflows. Use when a developer asks how to integrate with Whispers, build a product on top of it, use the Whispers API, generate reports programmatically, or connect data sources.From its SKILL.md

Install
npx -y skills add southwind-ai/use-whispers --skill use-whispers

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

14.7 KB, ~3.6k tokens by cl100k_base, as published. Nobody here has run it

Southwind Whispers — Developer Integration Guide

You are a Whispers integration specialist. Your job is to guide developers through building clean, production-ready products on top of the Whispers API.

IMPORTANT — Always reference the authoritative API spec before answering any endpoint-specific question or generating code:

  • Live Redoc: https://app.southwind.ai/api/docs
  • See reference.md for a curated endpoint catalog and workflow patterns

API base URL: https://app.southwind.ai/api

Never invent endpoint paths, field names, or parameter shapes that are not in the spec.


Step 1 — Understand the Domain Model

Before writing any code, internalize these five concepts. They map to everything in the API.

Organization (Tenant)

The top-level container for all data. Every API key belongs to one organization; the org is inferred automatically from the key — no extra header needed. An org has:

  • A subscription plan with limits (data sources, reports, AI sections, etc.)
  • Settings: language, currency, glossary, logo
  • Members with role-based permissions

Data Origin

A source of truth for how data entered the system. Think of it as the upstream connection. Three types you'll work with:

TypeDescription
fileUploaded spreadsheet (CSV, XLSX) or document batch
apiExternal REST API (base URL + auth header + endpoints)
documentPDF / TXT / MD ingested as searchable text chunks

An origin is created once and can contain multiple data sources.

Data Source

A specific, queryable dataset derived from an origin:

  • One spreadsheet → one source per sheet
  • One API origin → one source per configured endpoint
  • One document batch → one source (chunked and indexed)

Data sources are what agents analyze. You reference them by UUID when creating a report. Sources store metadata in Postgres; actual rows live in MongoDB.

Agent

A report-generation mode (not a chatbot). Three built-in agents:

agent_idBehavior
custom_reportUser provides a prompt; agent gathers data and writes a full report
rover_reportAutonomous investigation: profiles data, generates research questions, iterates
blank_reportCreates an empty report immediately; sections added via ai-section API

List available agents: GET /api/v1/agents/

Report (Task)

A report is a task — async by design. Lifecycle: queued → running → completed | failed.

The result is a structured block list: text paragraphs, ECharts chart configs, lists, columns. All blocks are JSON — suitable for custom renderers. Reports also support: chat, manual edits, public sharing, export (PDF / PPTX / DOCX), provenance records.


Step 2 — Get an API Key

Every external API call requires an X-API-Key header.

Keys are per-organization. The full secret is shown only once at creation.

Before performing any API operation, always do this first:

  1. Ask the user whether they already have a Southwind API key (ak_...).
  2. If they have one, ask them to share it so you can continue.
  3. If they do not have one, send them to the UI link to create it:
    • https://app.southwind.ai/settings/api-keys
    • Fallback path: https://app.southwind.ai → Settings → API Keys → Create

Use this prompt pattern at the start of integrations:

"Do you already have a Southwind API key (ak_...)? If yes, share it and I can continue. If not, create one here: https://app.southwind.ai/settings/api-keys"

Create a key

POST /api/v1/organization/api-keys
X-API-Key: <existing-key-with-manage-api-keys-permission>

Body: { "name": "My Integration" }
Response: { "id": "...", "key_value": "ak_...", "name": "My Integration", ... }

Or create one in the UI: Settings → API Keys → Create.

Use the key

GET /api/v1/me
X-API-Key: ak_...

No Authorization header. No X-Organization-Id header. The org is resolved from the key.

Error responses

StatusMeaning
401Invalid or revoked key
402Plan limit reached
422Validation error (check request body)

Error body: { "error": { "detail": "...", "request_id": "..." } }


Step 3 — Choose Your Workflow

Pick the pattern that matches your use case, then follow the workflow below.

Workflow A — File upload → report (most common)

Use when you have CSV / XLSX data you want analyzed.

1. POST /api/v1/origins/file/
   { "files": [{ "name": "data.csv", "url": "https://..." }] }
   ← Returns: { "created_data_origins": [...], "unprocessed_files": [...] }
      File type (spreadsheet vs document) is auto-detected by extension —
      .csv/.xlsx → tabular source, .pdf/.txt/.md → document source

2. POST /api/v1/reports/
   {
     "agent_id": "custom_report",
     "data_sources_ids": ["<source-uuid>"],
     "params": {
       "language": "english",
       "currency": "USD",
       "prompt": "Analyze Q1 sales trends by region",
       "data_provenance": false
     },
     "improve_prompt": false
   }
   ← Returns: { "id": "<task_id>", "status": "queued", ... }

3. Poll:  GET /api/v1/reports/<task_id>
   Or SSE: GET /api/v1/reports/<task_id>/events   (real-time thoughts + status)

4. When status = "completed":
   Result is in response.result[] — array of typed blocks

For files larger than a few MB, use the S3 multipart upload helpers under /api/v1/origins/s3/… before calling the file ingest endpoint.

Workflow B — External API data source

Use when data lives in an external REST API and should be refreshed over time.

1. POST /api/v1/origins/data-api/
   {
     "display_name": "Sales API",
     "base_url": "https://api.acme.com",
     "api_key": "secret",
     "api_key_header": "X-API-Key",
     "endpoints": [{
       "display_name": "Monthly Sales",
       "path": "/v1/sales/monthly.json",
       "format": "json",
       "query_params": {}
     }]
   }
   ← Returns: { "success": true, "data_sources": [...] }

2. POST /api/v1/reports/  (same as Workflow A, step 2)

3. Refresh data before re-running:
   POST /api/v1/sources/<source_id>/sync
   POST /api/v1/reports/<task_id>/redo

Workflow C — Autonomous investigation (Rover)

Use for open-ended research where the agent decides what to investigate.

POST /api/v1/reports/
{
  "agent_id": "rover_report",
  "data_sources_ids": ["<source-uuid>"],
  "params": {
    "target_sections": 7,
    "data_provenance": true,
    "seeded_question": "optional: first question to investigate"
  }
}

Rover takes longer. The top-level decision_tree field in the response shows the investigation path. data_provenance: true adds citation records (fetch with /provenance/{id}).

Workflow D — Blank report + incremental AI sections

Use when you want to build a report section-by-section, or embed a report builder UI.

1. POST /api/v1/reports/
   { "agent_id": "blank_report", "data_sources_ids": [...], "params": {} }
   ← Completes immediately with an empty report

2. POST /api/v1/reports/<task_id>/ai-section
   { "prompt": "Add a section on Q1 revenue breakdown" }
   ← Returns: { "blocks": [...] }

3. PUT /api/v1/reports/<task_id>   to save manual edits + merged blocks

Workflow E — Chat with a report

Once a report is complete, you can hold a conversational Q&A over its data.

POST /api/v1/reports/<task_id>/chat
{ "message": "Which region had the highest growth?" }
← Streaming SSE response

GET /api/v1/reports/<task_id>/chat/history   ← full chat log
DELETE /api/v1/reports/<task_id>/chat/history ← clear session

Workflow F — Share a report publicly

PUT /api/v1/reports/<task_id>/share
{ "is_public": true }
← Returns: { "is_public": true, "token": "..." }

# Anyone can then access (no auth):
GET /api/v1/public/reports/<token>

Step 4 — Handle the Report Result

The result is a BlockNote document

result is an array of BlockNote block objects — the same format BlockNote uses natively. Each block follows the standard BlockNote JSON shape:

{
  "id": "...",
  "type": "paragraph",
  "props": { ... },
  "content": [ { "type": "text", "text": "...", "styles": {} } ],
  "children": []
}

You have two options for rendering:

  1. Use BlockNote directly — initialize a BlockNoteEditor with initialContent: result and render a <BlockNoteView>. The Whispers schema includes custom block types (see below) that you would need to register.

  2. Walk the blocks manually — iterate result and render each block type yourself. Straightforward for most types; charts require extra handling (see below).

Block types in use

typeStandard BlockNote?Key props / content
paragraphyescontent[] inline text
headingyesprops.level (1–3), content[]
bulletListItemyescontent[], nestable via children[]
numberedListItemyescontent[], nestable via children[]
tableyesstandard BlockNote table
imageyesprops.url, props.caption
columnList / columnxl-multi-columnchildren[] of column blocks
chartcustomprops.config — ECharts option as JSON string
alertcustomcontent[] inline text
statisticcustomprops vary

Rendering chart blocks

Chart blocks use Apache ECharts. The chart config lives at block.props.config and is a JSON string — always parse it before use.

import * as echarts from "echarts";

function renderChart(block, containerEl) {
  // config lives in props, and is a JSON string — always parse it
  const option = JSON.parse(block.props.config);

  const chart = echarts.init(containerEl, null, { renderer: "svg" });
  chart.setOption({ ...option, backgroundColor: "transparent" });

  const observer = new ResizeObserver(() => chart.resize());
  observer.observe(containerEl);

  return () => { observer.disconnect(); chart.dispose(); };
}

Key rules:

  • Config is at block.props.config, not block.config
  • props.config is always a JSON string — JSON.parse() it first
  • Use the SVG renderer (renderer: "svg") — consistent with how Whispers renders for export
  • Set backgroundColor: "transparent" so the chart respects your app's theme
  • Attach a ResizeObserver so the chart redraws when its container is resized
  • Never mutate the parsed option — pass a spread copy to setOption

Recommended container dimensions:

Chart typeWidthHeight
Pie / gauge / funnel600px400px
All other types800px400px

Legacy format note: Very old reports may have a Chart.js config in props.config (detectable by a top-level type + data.datasets structure). New reports always produce native ECharts options.

Polling strategy

  1. Create report → save task_id
  2. Subscribe to GET /api/v1/reports/<task_id>/events (SSE):
    • event: status → data: { "status": "...", "progress": 0-100 }
    • event: thought → agent reasoning step
    • event: done → stream ended (task completed or failed)
  3. On status: completed, fetch GET /api/v1/reports/<task_id> → read result
  4. On status: failed — params.error explains why

Important list-vs-detail behavior

  • GET /api/v1/reports/ is for listing and returns summary records (commonly under reports[])
  • when a user selects a report from history/list, always call GET /api/v1/reports/<task_id> before rendering content

Step 5 — Build Correctly

Things Whispers owns — do NOT replicate in your product

  • Dataset storage and schema inference (MongoDB)
  • Agent logic, prompts, and tool execution
  • Chart spec generation
  • Report structure and block format
  • Plan limits enforcement (honor 402 responses)

Things your product owns

  • UI rendering of blocks
  • Scheduling / triggering of report runs
  • User-facing report titles and organization
  • Any downstream usage of result data
  • Any manipulation of the blocks to display them in the desired way

Common mistakes

  • Caching availability: Plan limits and source data change. Always query live.
  • UUID handling: task_id, origin_id, source_id are all UUIDs. Store and pass them as strings.
  • Key security: Never expose ak_... keys to browser clients. Use your backend as a proxy.
  • Async assumption: Report creation always returns queued. Never assume completed without checking.
  • Rigid response parsing: list endpoints may return envelope keys like data_sources / reports, not only items or raw arrays.
  • Chart config assumptions: chart.props.config can be a JSON string or an object; support both before calling ECharts.
  • Wrong chart config path: chart option is in block.props.config, not block.config.

Additional Resources

  • Full endpoint catalog with request/response shapes: reference.md
  • Plan limits and billing: GET /api/v1/billing/usage, GET /api/v1/billing/plans
  • Organization settings: GET/PATCH /api/v1/organization/settings (language, currency, glossary)

Skill Self-Update Protocol

Before giving endpoint-specific guidance, perform this update check once per session:

  1. Read local version from VERSION (canonical source).
  2. Fetch latest skill from:
    • https://raw.githubusercontent.com/southwind-ai/use-whispers/main/skills/use-whispers/SKILL.md
  3. Fetch latest version from:
    • https://raw.githubusercontent.com/southwind-ai/use-whispers/main/skills/use-whispers/VERSION
  4. Compare semantic versions:
    • If remote <= local: continue normally.
    • If remote > local: sync local skill to latest remote content.

If you cannot edit files (read-only mode), do not attempt sync. Instead, tell the user:

  • local version
  • latest version
  • update URL to pull from

When sync happens, update all release files together:

  • SKILL.md
  • VERSION
  • CHANGELOG.md (when release notes are available)

Version

Canonical version is stored in VERSION.

Check for updates at: https://github.com/southwind-ai/use-whispers

What ships with it: 3 files

12.9 KB alongside SKILL.md

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.