# Shared analysis skills and routines

Saved company skills are instructions shown in CrowdListen Insights. They are distinct from the packaged SKILL.md methodology guides. The browser and connected agents use the same definitions and permissions; no additional MCP tools are installed.

## Read and configure

```javascript
recall({mode: "skills", entity_id: "COMPANY_UUID"})
recall({mode: "routines", entity_id: "COMPANY_UUID"})
recall({mode: "skill_runs", entity_id: "COMPANY_UUID"})
```

Skills returns `{entity_id, skills}`. Each skill has `id`, `title`, `question`, `decision`, `evidence`; preserve IDs when editing. There may be at most five. Save the full desired list, retaining other definitions, with the exact list you read as the concurrency precondition:

```javascript
ingest({destination: "skills", entity_id: "COMPANY_UUID",
  expected_skills: [],
  skills: [{id: "launch-review", title: "Launch engagement",
    question: "Which launch posts receive replies?",
    decision: "Choose topics for the next launch",
    evidence: "Saved X posts and captured measurements; disclose missing counts and different post ages."}]})
```

This creates configuration only. It does not launch collection, analysis, or a schedule. On HTTP 409, reread and merge the user's changes before saving. An identical desired-state retry is safe after a lost acknowledgement. Viewers may read; only current editors may configure or run. The server derives actor and workspace identity.

## Run once

For hosted reasoning:

```javascript
analyze({action: "skill", entity_id: "COMPANY_UUID", skill_id: "launch-review", request_id: "NEW_UUID"})
analyze({action: "status", job_id: "RETURNED_JOB_UUID"})
```

The same durable endpoint as the UI freezes the selected definition and uses saved originals. Reuse the request_id to recover an interrupted acknowledgement; do not override the question or pass live collection options with action skill. A queued receipt is not a completed analysis. Read status, coverage and errors, then recall the persisted findings.

For reasoning in the user's own client, read the skill and authorized knowledge_source originals, reason with the client's model, then save exact-cited findings using ingest destination insight and verify readback. Do not invoke hosted analyze unless hosted reasoning was chosen. Own-client model usage is billed by that provider. Hosted run history does not record external execution; saved findings remain shared.

## Schedule or pause

Only enable a routine when the user has requested recurring hosted execution with the cadence, source scope and maximum per-run charge. Read existing routines first. Use expected_revision 0 for a new schedule or the returned revision when editing/pausing:

```javascript
ingest({destination: "routine", entity_id: "COMPANY_UUID", skill_id: "launch-review",
  routine: {enabled: true, interval_hours: 168, source_mode: "saved",
    max_charge_cents: 200, expected_revision: 0}})
```

Cadence is daily (24) or weekly (168). Source mode saved analyzes stored originals; refresh collects configured X accounts first. max_charge_cents is required, from 1 to 10000. It is a per-run ceiling, not a total subscription budget. Routines run on CrowdListen and do not require the desktop agent to stay open. Setting enabled:false pauses future runs but does not cancel an already queued job. Use the latest revision and retain the other settings.

recall mode routines reports scheduler_enabled and scheduler_last_seen_at. Configuration is not proof of a healthy worker, provider coverage, or a completed run. The server rejects enabled schedules when recurring execution or usage metering is disabled. Revoked access and removed skills prevent later dispatch. Do not report success after a failed write.

## Release requirements

These modes require the matching API, MCP/harness and shared-skill SQL migration. Local tests do not establish published-package or production availability. Existing skill/run/routine APIs, authorization, billing and workers are reused. Publish the matching harness before distributing these commands to installed clients.


# Daily workflow authoring

A workflow reuses a saved skill ID. Read the entire current list, edit one definition, and PUT the full desired list with `expected_skills` equal to the last-read list. Conflicts require rereading and merging. Source selection and instructions are shared with the Workflows page; a definition save neither runs nor schedules work.

```json
{
  "id": "slack-feedback", "title": "Daily product feedback",
  "question": "Which recurring problems need attention?",
  "decision": "Choose fixes and customer follow-ups.",
  "evidence": "Original messages and accessible thread replies from selected channels.",
  "workflow": {
    "version": 1,
    "instructions": "Separate first-hand problems, requests and praise. Preserve disagreement. Cite exact messages and propose a concrete next step. Do not infer prevalence from this sample.",
    "inputs": {"platforms": ["slack"], "account_roles": [],
      "slack_channels": [{"team_id": "YOUR_TEAM_ID", "channel_id": "YOUR_CHANNEL_ID", "name": "all-crowdlisten"}],
      "lookback_days": 7, "max_sources": 25}
  }
}
```

Replace the channel placeholders with IDs returned by the user's connected Slack workspace; names are labels. Bot access does not imply access to all channels that the human belongs to. Thread replies can require additional access; missing replies make collection partial. X uses configured accounts (up to five, optionally filtered by roles), not a site-wide keyword search. Empty platforms means all **saved** source types and cannot be used for a fresh pull. Windows overlap intentionally; original records deduplicate, acquisitions retain observations. Bounds can omit busy-channel history; this is not a guaranteed complete message archive.

## HTTP

- GET/PUT `/api/entities/{entity_id}/skills`: shared definitions; PUT body `{skills, expected_skills}`.
- POST `/api/entities/{entity_id}/skills/{skill_id}/runs`: saved-source execution. Add `?source_mode=refresh` for a pull, enrichment and synthesis. Header `Idempotency-Key` (8–128 chars); keep it on a lost response. A changed mode requires a new key. Accepted runs pin the definition.
- GET `/api/entities/{entity_id}/skill-runs`: recent runs, frozen definition, collection receipt, source count and coverage errors.
- GET `/api/entities/{entity_id}/skill-routines`: schedules and scheduler heartbeat.
- PUT `/api/entities/{entity_id}/skills/{skill_id}/routine`: `{enabled, interval_hours:24, source_mode:"refresh", max_charge_cents:200, expected_revision:0}`. Use the current revision for edits. Enabling authorizes recurring paid work; pause with `enabled:false` and the current revision. First occurrence is 24 hours after enabling; missed occurrences coalesce instead of creating a catch-up storm. Pausing does not cancel a running job.

All routes require current entity permission. Selection is separate from connection access. Managed calls reserve and settle the existing shared AWB balance, with a 4× measured API/model-cost price. Zero-charge Slack API reads are recorded; downstream models retain normal token receipts. Missing usage/balance prevents work or triggers reconciliation; never invent a price.

## MCP (matching updated harness required)

Use `recall({mode:"skills",entity_id})`, `ingest({destination:"skills",entity_id,skills,expected_skills})`, `analyze({action:"skill",entity_id,skill_id,source_mode:"refresh",request_id})`, and `recall({mode:"skill_runs",entity_id})`. Schedule through `ingest({destination:"routine",entity_id,skill_id,routine})` after explicit user instruction to enable paid recurring work. The public tools remain recall, analyze and ingest.

Own-agent reasoning reads the definition and scoped original records, applies the input filters/instructions, then saves exact-cited findings through `ingest(destination:"insight")`. That does not create an unattended desktop worker. A coding agent can author this JSON or run its own custom code externally; CrowdListen v1 does not execute arbitrary submitted code.

### X topic collection

`workflow.inputs.x_queries` optionally supplies up to three explicit X queries (1–480 characters each). Clear `account_roles` for topic search. Nonempty queries replace tracked-account collection, so a workflow can listen beyond known accounts. The managed collector uses the same usage ledger, stores originals and dated engagement, reuses known author identities and does not automatically request paid author-profile expansions. It resumes capped pages before advancing the date window. Recent search cannot cover more than seven days; expired unfinished windows report a gap.

Read the saved definition before editing, preserve other workflows, and start a metered run with `analyze({action:"skill", entity_id, skill_id, request_id, source_mode:"refresh"})`. An older installed harness can run/read the saved workflow; discovering/editing the new query field requires a matching tool schema. Local build success is not an npm release.

Workflow source filters may include `x_language` and `x_min_likes`. The provider query applies these before a topic search; account feeds and saved records are filtered using captured metadata before processing. Missing language/engagement does not pass a specified filter. Numeric author IDs belong in source metadata, never a readable finding.

A workflow can choose `synthesis_model: "gpt-5.5"` or `"gpt-5.4-mini"`, and `filter_relevance: true` for Jev relevance screening. Preserve other fields when editing with the optimistic-concurrency `expected_skills` contract. Model choice changes managed usage cost, and GPT-5.5 does not silently fall back. Originals excluded by workflow filters stay saved; inspect the run's `processing_selection` and `relevance_filter` receipts.

For customer browser collection, use the customer's authorized X browser, sign into CrowdListen through the harness, read the saved workflow filters, and ingest original batches plus coverage. An MCP login does not authenticate X. Do not send browser session cookies to CrowdListen. Hosted X collection continues to use the official API until an authenticated browser connector has been separately verified.
