{"skill":{"slug":"smart-news","displayName":"Smart News","summary":"Use when calling the Crypto News Analyzer HTTP API for async analysis jobs, semantic search, datasource management, intelligence operations, or health checks...","description":"---\nname: smart-news\ndescription: Use when calling the Crypto News Analyzer HTTP API for async analysis jobs, semantic search, datasource management, intelligence operations, or health checks from OpenClaw.\nmetadata: { openclaw: { skillKey: smart-news, primaryEnv: API_KEY } }\n---\n\n# Crypto News HTTP API Skill\n\nUse this skill to call the Crypto News Analyzer HTTP API from OpenClaw.\n\n## When to Use\n\nUse this skill when you need to call `https://news.tradao.xyz` or a compatible private deployment.\n\nTypical triggers:\n\n- Run asynchronous crypto news analysis over a time window\n- Run asynchronous unified semantic search (News + Intelligence) for a freeform topic query\n- Poll an API job until it finishes and then fetch the final result\n- Create, list, or delete datasources through the HTTP API\n- Query and manage intelligence topics through the topic-first API (create, revise, confirm, merge findings, detail, list, archive)\n- View and manage topic-datasource associations (get, set, add, remove) to scope topic research\n- List intelligence topic research run logs per-topic or globally\n- Check service health before or after an API workflow\n\n## Quick Reference\n\nAuthentication is Bearer token style: send `Authorization: Bearer <API_KEY>` with every request.\n\n`POST /analyze` creates a job and returns immediately. It does **not** return the final report. Poll status, then fetch the result.\n\nWorkflow: `POST /analyze` -> `GET /analyze/{job_id}` -> `GET /analyze/{job_id}/result`\n\nJobs move through these states: `queued`, `running`, `completed`, `failed`.\n\n`POST /semantic-search` creates a job, returns `202 Accepted`, and includes `status_url`, `result_url`, plus a `Retry-After` header. When `hours` exceeds the server max (720h default), a `warning` field describes the truncation. Semantic search jobs that do not complete within 5 minutes are automatically failed with a timeout error.\n\nSemantic workflow: `POST /semantic-search` -> `GET /semantic-search/{job_id}` -> `GET /semantic-search/{job_id}/result`\n\nUnified semantic search retrieves from both `content_items` and `raw_intelligence_items` via PostgreSQL with pgvector HNSW indexes (`embedding vector(1536)`). SQLite runtime is unsupported.\n\nFor detailed guides, see:\n\n- [Analyze Workflow Reference](references/analyze-workflow.md)\n- [Semantic Search Reference](references/semantic-search.md)\n- [Datasource Management Reference](references/datasource-management.md)\n- [Intelligence Query Reference](references/intelligence-query.md)\n- [Operations and Maintenance Reference](references/operations-and-maintenance.md)\n\n## OpenClaw Runtime\n\nThis skill declares `metadata.openclaw.primaryEnv: API_KEY`. In OpenClaw, inject the bearer token through `~/.openclaw/openclaw.json`:\n\n```json5\n{\n  skills: {\n    entries: {\n      \"smart-news\": {\n        enabled: true,\n        apiKey: \"YOUR_API_KEY\"\n      }\n    }\n  }\n}\n```\n\nIf `apiKey` is unavailable, do not send unauthenticated requests. Ask the operator to configure the token first.\n\nIf you are using a non-production deployment, replace `https://news.tradao.xyz` with the correct base URL before issuing requests.\n\n## Analyze Workflow\n\nCreate an analysis job by posting to `/analyze` with `hours` and `user_id`. The server responds with `202 Accepted`, a `job_id`, `status_url`, and `result_url`.\n\nPoll the status endpoint until the job reaches `completed` or `failed`. Do not expect the analysis report in the initial POST response. Once completed, fetch the result URL.\n\n## Semantic Search\n\nUnified semantic search retrieves from both News (`content_items`) and Intelligence (`raw_intelligence_items`) domains via UNION ALL over pgvector HNSW indexes. The response includes a `source_breakdown` with per-domain `matched_count` and `retained_count`. Each hit carries a `source_domain` discriminator (`\"news\"` or `\"intelligence\"`).\n\nCreate a semantic search job by posting to `/semantic-search` with `hours`, `query`, and `user_id`. The server responds with `202 Accepted`, a `job_id`, `status_url`, and `result_url`. Semantic search job IDs start with `semantic_search_job_`.\n\nPoll the status endpoint until the job reaches `completed` or `failed`, then fetch the report from the result URL. Use the `status` field as the source of truth for lifecycle state; `success` becomes `true` only when the job is completed successfully.\n\nRequest rules:\n\n- `hours` must be a positive integer\n- `query` is required, trimmed, and capped at 300 characters\n- `query` cannot be blank or whitespace-only\n- `user_id` must match `^[A-Za-z0-9_-]{1,128}$`\n\nOperational constraints:\n\n- Semantic search is PostgreSQL-only and returns `503` when the backend does not support pgvector\n- Both `content_items` and `raw_intelligence_items` tables have `embedding vector(1536)` columns with HNSW indexes (`idx_content_embedding_hnsw` and `idx_intelligence_embedding_hnsw`)\n- The API uses vector similarity over stored content embeddings and combines that with deterministic local keyword fallback (no LLM-driven keyword expansion)\n- LLM query decomposition is disabled by default (`query_planning_enabled: false`); when disabled the raw user query is embedded directly as the only subquery. The `max_subqueries` cap (4) only applies when query planning is explicitly re-enabled\n- Final retained results are capped at 200 unique items per domain before merging\n- Embedding generation requires `OPENAI_API_KEY`; report synthesis requires `KIMI_API_KEY` or `GROK_API_KEY` (query planning also requires an LLM key but is disabled by default)\n\nThe result body returns a Markdown report with `query`, `normalized_intent`, `matched_count`, `retained_count`, `time_window_hours`, `source_breakdown`, and `report`.\n\n## Datasource Management\n\nConfigure news and intelligence sources through the datasource API. Create sources with `POST /datasources`, list them with `GET /datasources`, and remove them with `DELETE /datasources/{id}`. All datasource routes require Bearer auth.\n\nEach datasource has a `purpose` field: `news` (RSS/X/REST feeds for analysis) or `intelligence` (Telegram groups, V2EX for topic research). The `GET /datasources` endpoint supports optional `purpose` and `source_type` query parameters for filtering. Results are sorted by purpose, source type, then name.\n\nTags help organize sources. Each datasource accepts up to 16 unique tags. Each tag is capped at 32 characters. Tags are normalized to lowercase and deduplicated automatically.\n\nList and create responses include only safe summaries. For `rest_api` type datasources, secrets are redacted and counts replace raw credential fields. This prevents accidental credential exposure when reviewing configurations.\n\n## Intelligence Query (Topic-First)\n\nAll intelligence routes require Bearer auth. The deprecated entry-based routes (`/intelligence/entries*`, `/intelligence/discovery`, `/intelligence/labels`, `/intelligence/search`) have been removed in the topic-only refactor. Topics are the sole first-class intelligence objects, driving scheduled LLM research from raw ingested messages and storing findings with merge support.\n\nSynchronous topic workflow endpoints:\n\n- `POST /intelligence/topics` — Create a topic draft from a user theme (returns AI-generated prompt draft)\n- `POST /intelligence/topics/{topic_id}/revise` — Revise the draft prompt with feedback\n- `PUT /intelligence/topics/{topic_id}/prompt` — Manually set/replace the prompt text (context-aware: edits active prompt if one exists, otherwise creates draft revision)\n- `POST /intelligence/topics/{topic_id}/confirm` — Confirm and activate the topic for research (requires `prompt_version_id`)\n- `GET /intelligence/topics` — List topics with pagination and `active_only` filter (default: true)\n- `GET /intelligence/topics/{topic_id}` — Get topic metadata and merge availability\n- `GET /intelligence/topics/{topic_id}/findings` — Get paginated active findings with citations and source URLs\n- `GET /intelligence/topics/{topic_id}/prompts` — Get prompt versions and current active prompt\n- `POST /intelligence/topics/{topic_id}/archive` — Archive a topic\n- `GET /intelligence/topics/{topic_id}/runs` — List topic research run logs\n- `GET /intelligence/topic-runs` — List all topic research runs globally\n\nThese endpoints are synchronous; there is no async job/poll flow. Results return immediately.\n\nAsync topic merge endpoint:\n\n- `POST /intelligence/topics/{topic_id}/merge` — Start an async merge job (returns 202 Accepted with `job_id`, `status_url`, `result_url`)\n- `GET /intelligence/topics/{topic_id}/merge/{job_id}` — Check merge job status\n- `GET /intelligence/topics/{topic_id}/merge/{job_id}/result` — Retrieve completed merge results\n\nMerge workflow: `POST /intelligence/topics/{id}/merge` → poll `GET .../merge/{job_id}` → `GET .../merge/{job_id}/result`. Jobs move through states: `queued`, `running`, `completed`, `failed`. The merge LLM call may take several minutes, so polling is required — do not block on the POST response.\n\nTopics have lifecycle states: `draft`, `active`, `archived`. Only `active` topics are researched by the ingestion scheduler. Finding merge is available through both the async HTTP endpoint and the Telegram `/topic_merge` command.\n\n## Telegram Webhook\n\nThe webhook endpoint exists for maintainer-level Telegram integration. It is not the primary path for day-to-day operators. Regular users should interact through the API routes or Telegram slash commands instead.\n\nWhen processing webhook updates, validate the `X-Telegram-Bot-Api-Secret-Token` header to confirm the request originates from Telegram.\n\n## Endpoint Index\n\nSupported HTTP routes:\n\n- `GET /health` - Service health check\n- `POST /analyze` - Create an analysis job (async, returns 202)\n- `GET /analyze/{job_id}` - Check job status\n- `GET /analyze/{job_id}/result` - Retrieve completed job results\n- `POST /semantic-search` - Create a semantic search job (async, returns 202)\n- `GET /semantic-search/{job_id}` - Check semantic search job status\n- `GET /semantic-search/{job_id}/result` - Retrieve completed semantic search results\n- `POST /datasources` - Create a datasource\n- `GET /datasources` - List all datasources\n- `DELETE /datasources/{id}` - Delete a datasource\n- `POST /telegram/webhook` - Telegram webhook receiver\n- `POST /intelligence/topics` - Create topic draft (synchronous, Bearer-protected)\n- `POST /intelligence/topics/{id}/revise` - Revise topic prompt\n- `PUT /intelligence/topics/{id}/prompt` - Manually set topic prompt\n- `POST /intelligence/topics/{id}/confirm` - Confirm and activate topic\n- `GET /intelligence/topics` - List topics with status filters\n- `GET /intelligence/topics/{id}` - Get topic metadata and merge availability\n- `GET /intelligence/topics/{id}/findings` - Get paginated findings with citations\n- `GET /intelligence/topics/{id}/prompts` - Get prompt versions and active prompt\n- `POST /intelligence/topics/{id}/archive` - Archive topic\n- `POST /intelligence/topics/{id}/merge` - Start async merge job (returns 202)\n- `GET /intelligence/topics/{id}/merge/{job_id}` - Check merge job status\n- `GET /intelligence/topics/{id}/merge/{job_id}/result` - Retrieve completed merge results\n- `GET /intelligence/topics/{id}/datasources` - List datasource associations for a topic\n- `PUT /intelligence/topics/{id}/datasources` - Replace all datasource associations atomically\n- `POST /intelligence/topics/{id}/datasources/{datasource_id}` - Add a datasource association (idempotent)\n- `DELETE /intelligence/topics/{id}/datasources/{datasource_id}` - Remove a datasource association (idempotent)\n- `GET /intelligence/topics/{id}/runs` - List topic research run logs\n- `GET /intelligence/topic-runs` - List all topic research runs globally\n\n## Non-Goals\n\nThis skill does not cover:\n\n- Telegram slash commands (use the Telegram bot directly)\n- Autogenerated documentation routes (`/docs`, `/redoc`, `/openapi.json`)\n- Deprecated compatibility aliases are not part of the active runtime surface\n- Direct embedding backfill operations beyond pointing you to the documented command\n\nThese surfaces exist but are intentionally excluded from this API-focused skill.\n\n## Updating\n\nKeep this skill aligned with the live HTTP routes in `api_server.py`, the AI Analyze API Guide at `docs/AI_ANALYZE_API_GUIDE.md`, the semantic search guide at `docs/SEMANTIC_SEARCH_API_GUIDE.md`, and the domain repository contracts in `domain/repositories.py`.\n\nWhen documentation disagrees with implementation, trust the code and tests over prose docs. Source precedence: code first, then reference files, then guides.\n","topics":["News","Crypto","Health"],"tags":{"latest":"0.4.6"},"stats":{"comments":0,"downloads":661,"installsAllTime":25,"installsCurrent":0,"stars":0,"versions":8},"createdAt":1779097790423,"updatedAt":1780717234958},"latestVersion":{"version":"0.4.6","createdAt":1780717234958,"changelog":"Sync lifecycle to archive-only; remove /pause route and /topic_pause Telegram surface; fix startup flags; correct test paths; align docs with code.","license":"MIT-0"},"metadata":{"setup":[],"os":null,"systems":null},"owner":{"handle":"laceletho","userId":"s1711j71qhdb72tgw6r3r22ra184d1mn","displayName":"Letho","image":"https://avatars.githubusercontent.com/u/3763819?v=4"},"moderation":null}