agentsclimarketplace

Use whispers

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

Official AI agent skill and documentation for Southwind Whispers.

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.

What its author says it does

Copied from the file, not written here

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.

SKILL.md

14.7 KB, 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.aiSettingsAPI KeysCreate

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 stringJSON.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: statusdata: { "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: failedparams.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

Keep looking

Skills are one crate of 328,083. 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.