# Skywatch Working The Queue

> OODA-based moderation queue triage — observe reports, orient with context and policy, decide on classification, act on user-confirmed decisions. Supports multiple entry points (reports, appeals, tags, proactive filtering). Use when triaging the Ozone moderation queue or processing moderation reports.

- **Type:** Skill
- **Install:** `agentstack add skill-skywatch-bsky-skywatch-agent-skills-skywatch-working-the-queue`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [skywatch-bsky](https://agentstack.voostack.com/s/skywatch-bsky)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [skywatch-bsky](https://github.com/skywatch-bsky)
- **Source:** https://github.com/skywatch-bsky/skywatch-agent-skills/tree/main/polytoken/skills/skywatch-working-the-queue
- **Website:** https://bsky.app/profile/skywatch.blue

## Install

```sh
agentstack add skill-skywatch-bsky-skywatch-agent-skills-skywatch-working-the-queue
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Working the Queue

This skill guides moderation queue triage using an OODA loop: **observe** the report, **orient** with additional context and policy guidance, **decide** whether it violates a policy, then **act** on user-confirmed decisions. The goal is efficient batch processing where the analyst reviews AI recommendations rather than raw reports.

### Subagent Model Selection

The primary triage agent delegates work to subagents to preserve its context window:

| Task | Model | Rationale |
|------|-------|-----------|
| Per-subject data collection & recommendation (Phase 1) | `data-analyst` | Speed |
| Follow-up investigation queries (Phase 1) | `data-analyst` | Additional ClickHouse or Ozone queries when initial evidence is insufficient |
| Ozone read queries (queue pulls, event history) | `data-analyst` | Rote data retrieval; return structured summaries to the supervisor |
| Action execution — labelling, acknowledging, escalating (Phase 3) | `general-purpose-mini` | Mechanical execution of a pre-built manifest; no judgment required |

The primary Opus agent makes all classification and presentation decisions. Everything else — data gathering, Ozone queries, action execution — is delegated. Pass subagents the information they need (DIDs, AT-URIs, labels, comments, batchIds) and receive summaries or execution confirmations back.

## Prerequisites

### Load Reference Skill

Load the `skywatch-querying-ozone` skill for Ozone tool parameter guidance, filter combinations, and conventions.

### Load Policy Guidance

Check for a `.policies/` directory in the current working directory. Read all files within it — these contain label definitions, enforcement criteria, and policy guidance that inform classification decisions.

If `.policies/` also contains a `precedents/` subdirectory, read those files too. Precedents are prior analyst decisions on ambiguous cases that serve as case law for future classification.

If no `.policies/` directory is found, warn the user: "No .policies/ directory found in the current working directory. Proceeding without policy-specific guidance — classifications will be based on general moderation principles. Consider creating .policies/ with your label definitions and enforcement criteria."

## Input

Two parameters, both provided by the user:

- **Entry point** — what to pull from the queue. Determines the `mcp__skywatch-mcp__ozone_query_statuses` filter:

| Entry Point | Query Pattern |
|-------------|--------------|
| Recent reports | `sort_field: "lastReportedAt"`, `sort_direction: "desc"` |
| Appeals | `appealed: true`, `sort_direction: "desc"` |
| By tag | `tags: [user-specified]`, `sort_direction: "desc"` |
| By review state | `review_state: [user-specified]` |
| Proactive (custom filters) | User-specified combination of filters |
| Specific subject | `subject: [DID or AT-URI]` — single-subject mode |

- **Batch size** — how many subjects to pull. No default — ask the user if not specified. The user may say "all appeals" or "20 recent reports" or "everything tagged follow-up."

## Phase 1: Scan & Classify

For each subject in the batch, gather context and produce a classification. This is the first pass — prioritise speed and coverage over depth.

### Subject Granularity

Moderation labels apply at both the account level and the individual post level. When the queue contains multiple reported posts from the same account, **do not roll them up or deduplicate.** Each reported post requires individual review because:

- Different posts may violate different policies (or none at all)
- A post-level label targets specific content; an account-level label reflects systemic behaviour
- The aggregate pattern across multiple reported posts informs whether account-level action is warranted, but that is a separate decision from post-level findings

Treat each reported AT-URI as its own subject. Use the account-level view (content context, moderation history) as supporting evidence for each post-level decision.

However, the agent should proactively recommend account-level labels when the evidence supports it — even if only individual posts were reported. Triggers for an account-level recommendation:

- Multiple reported posts from the same account show a consistent pattern of the same policy violation
- Reviewing an individual post's content context (step 2) reveals a broader pattern of violating behaviour beyond the reported content
- The account's rule hit history shows sustained, repeated matches against the same rules

When recommending an account-level label, add it as a separate classification entry alongside the post-level entries. The analyst decides whether to apply both, one, or neither.

### Data Limitation: ClickHouse Window

ClickHouse (`osprey_execution_results`) retains approximately 2 months of data. This is a partial view of an account's history, NOT the complete picture. Thin or absent ClickHouse results mean the data hasn't been indexed — not that the account has no content. **Never conclude an account has "zero content" or "nothing to evaluate" based solely on ClickHouse returning few or no results.**

When ClickHouse data is insufficient and the reporter's claims cannot be verified, note this in the classification as `investigate_further` or flag it to the analyst. **Do NOT automatically fetch additional posts from the PDS** — reserve deeper content fetching for when the analyst explicitly requests more context.

### Per-Subject Data Collection

For each subject, dispatch the `data-analyst` subagent to gather context. Use the `data-analyst` for speed — Opus is too slow for per-subject data collection across a batch. The subagent collects all four categories below and returns a structured summary. This preserves the triage agent's context window for classification decisions across the full batch.

**Subagent prompt pattern:**

> Gather moderation context for subject [DID or AT-URI]. **ClickHouse is your primary data source** — it's cheap and fast. Only fall back to querying the PDS directly (PDSX tools) when ClickHouse cannot provide what you need (e.g., the account pre-dates the ClickHouse window, or the account has been taken down and PDS records are unavailable).
>
> Collect in this order:
> (1) **Rule hits** — query ClickHouse osprey_execution_results for all rule hits for this DID in the past 30 days, grouped by rule name with counts. This is the cheapest signal and should be checked first.
> (2) **Content context** — 5 most recent posts from this DID via ClickHouse osprey_execution_results with post text, timestamps, and matched rules.
> (3) **Profile** — fetch the account's profile via ClickHouse if available, otherwise fall back to `mcp__pdsx__get_record` (PDSX, uri `app.bsky.actor.profile/self`, repo [DID]). Return the handle, display name, and bio/description verbatim. For taken-down accounts, ClickHouse is the only source — note if the profile fetch fails.
> (4) **Moderation history** — from `mcp__skywatch-mcp__ozone_query_events`: prior reports, labels, actions, sticky comments.
> (5) **Report details** — what was reported, by whom, what reason was given.
> (6) If the subject is a reply, **thread context** — the parent post, the account being replied to, and the relationship between the accounts.
>
> DATA SOURCE PRIORITY: ClickHouse first, always. It covers ~2 months of data and includes rule match context. Only use PDSX tools (`mcp__pdsx__get_record`, `mcp__pdsx__list_records`) as a fallback when ClickHouse has no data for this subject — e.g., the account pre-dates the indexing window, or you need a profile that isn't in ClickHouse. For taken-down accounts, ClickHouse may be the ONLY source of post content — the PDS will return errors.
>
> TOKEN BUDGET: Fetch a MAXIMUM of 5 posts for content context. If the subject is a reply, also fetch the thread context (parent chain up to 3 levels) — this does NOT count against the 5-post cap. Do NOT fetch additional posts beyond the cap. If 5 posts are insufficient for a confident classification, recommend `investigate_further` and note what additional context would help.
>
> CRITICAL: Return ALL content verbatim. Do NOT summarise, paraphrase, or excerpt. The analyst reviews the evidence and makes the decision — the agent's role is to gather and present, not to judge. Specifically return:
> (a) The account's handle, display name, and bio/description — verbatim.
> (b) The reported content verbatim (for post-level subjects). For replies, also return parent posts verbatim.
> (c) The full text of every post reviewed, with AT-URIs and timestamps.
> (d) Rule hit summary — which rules fired, how many times, over what period.
> (e) A recommended classification (label / no_action / investigate_further / escalate / defer) with a recommended label and label level if applicable.
> (f) The specific evidence supporting that recommendation — rule hit patterns, moderation history, thread context.
> (g) How many posts were reviewed and whether the 5-post cap limited the assessment (if so, note what additional context might change the recommendation).

The subagent should use the `data-analyst` subagent for ClickHouse queries and MCP tools directly for Ozone queries. Only use PDSX tools (`mcp__pdsx__get_record`, `mcp__pdsx__list_records`) as a fallback when ClickHouse cannot provide what's needed. The primary agent makes the final classification decision but uses the subagent's recommendation and evidence as input.

#### 1. Rule Hits (ClickHouse)

Query via data-analyst: pull all rule hits for DID [subject_did] from osprey_execution_results in the past 30 days, grouped by rule name with hit counts. This is the cheapest signal and often sufficient to determine whether an account is triggering relevant rules.

#### 2. Content Context (ClickHouse)

Query via data-analyst: pull the **5 most recent posts** from DID [subject_did] from osprey_execution_results. Return post text, timestamp, and any rules that matched.

**Do NOT automatically fetch additional posts from the PDS.** 5 posts plus rule hit summaries is sufficient for initial triage. Only fall back to PDSX `mcp__pdsx__list_records` if ClickHouse returns zero posts for this DID. If the evidence is insufficient, classify as `investigate_further` — the analyst can request deeper content fetching.

#### 3. Moderation History

Query `mcp__skywatch-mcp__ozone_query_events` for the subject. Look for:
- Prior reports (how many, how recent, what was reported)
- Prior labels (what's already applied)
- Prior actions (acknowledged, escalated, muted, appealed)
- Moderator comments (especially sticky comments from prior reviews)

This reveals whether the subject is a repeat offender, has prior context, or has already been reviewed.

#### 4. Report Content

From the `mcp__skywatch-mcp__ozone_query_statuses` result, examine the report itself — what was reported, by whom, and what reason was given.

**Reports are nominations, not evidence.** User reports are inherently noisy. A report tells you where to look — it does not tell you what you will find. The reporter's comment, reason, and framing are input to direct your investigation, never a source of evidence for or against the subject. Specifically:

- A reporter's comment is **never sufficient grounds to apply a label.** The evidence must come from the account's actual content, behaviour, and history.
- A reporter's comment is **never sufficient grounds to dismiss a report.** A vague, one-word, or poorly articulated report may still point to a real policy violation. The comment's quality says nothing about the subject's behaviour.
- **Do not psychoanalyse the reporter.** Do not infer the reporter's motives, political alignment, or whether they are acting in "good faith" or "bad faith." These are not observable and are irrelevant to the classification. The only question is: does the subject's actual content and behaviour violate policy?

**Label-name matching:** If the reporter's comment matches or closely resembles a label name from the loaded `.policies/` reference (e.g., "Blue Heart" → `blue-heart-emoji`, "MAGA" → `maga-trump`, "spam" → `spam`), treat it as a **label nomination** and verify the factual claim against the account's actual content and profile.

#### 5. Reply Thread Context

If the reported content is a reply, the reply MUST be evaluated in the context of its conversation before classification. A reply that looks like a policy violation in isolation may be entirely appropriate in context (or vice versa).

**Required steps for replies:**

1. **Pull the parent post.** Retrieve the post being replied to. If the parent is also a reply, pull its parent too — follow the chain up to 3 levels or until you reach the thread root, whichever comes first. The full conversational context determines whether the reply is appropriate.

2. **Identify the account being replied to.** Determine the DID of the account that authored the parent post. Gather basic context: is this a known account? Any prior moderation history? Any relationship signals?

3. **Check the relationship between accounts.** Determine whether the replier and the person being replied to follow each other. Mutual follows indicate a conversational relationship where different norms may apply — banter between mutuals reads differently than unsolicited hostile replies to strangers.

4. **Identify the reporter.** Determine whether the person who filed the report is the same person being replied to, or a third party. This matters:
   - **Reporter is the reply target:** they experienced the content directly and their report reflects first-person impact
   - **Reporter is a third party:** they observed the exchange but may lack context about the relationship between the participants. The reply may be part of an ongoing conversation that the reporter isn't privy to. Additional context is needed before acting.

5. **Synthesise.** Factor all of the above into the classification. A reply classified as potentially violating must have its thread context documented in `key_evidence` so the analyst can verify the contextual judgment.

### Follow-Up Investigation

The initial scan is intentionally lean (5 posts per subject). When the analyst requests more context — or when a subject is classified as `investigate_further` and the analyst approves deeper investigation — dispatch additional `data-analyst` subagents. **Do not proactively fetch additional posts beyond the initial 5 unless the analyst asks.**

Examples of follow-up dispatches (analyst-triggered):

- **More posts** — "Fetch up to 10 additional posts from DID [X] via ClickHouse or `mcp__pdsx__list_records` (PDSX tool, collection `app.bsky.feed.post`, repo [DID]). Return post text, AT-URIs, and timestamps." Cap at 10 posts per follow-up request.
- **Deeper ClickHouse queries** — "Pull all posts from this DID in the past 7 days that matched rule [X]. Return full post text and timestamps." or "Find all accounts that co-shared URLs with this DID in the past 7 days."
- **Thread expansion** — "Retrieve the full thread for AT-URI [X] — all replies, not just the parent chain."
- **Account relationship check** — "Determine the follow relationship between DID [A] and DID [B]. Check if they have prior interaction history."
- **Content similarity** — "Find posts across the network with similar text to [quoted content] using `mcp__skywatch-mcp__content_similarity`."
- **Additional moderation history** — "Pull full `mcp__skywatch-mcp__ozone_query_events` for DID [X] going back 90 days, not just the default."

The triage agent owns the classification decision. When evidence is thin, classify as `investigate_further` rather than guessing — let the analyst decide whether to invest tokens in deeper investigation.

### Batch-Level Bias Check

Processing subjects in batches creates a risk of **anchoring bias** — patterns observed in earlier subjects contaminate the evaluation of later ones. Guard against this:

- **Each subject is independen

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [skywatch-bsky](https://github.com/skywatch-bsky)
- **Source:** [skywatch-bsky/skywatch-agent-skills](https://github.com/skywatch-bsky/skywatch-agent-skills)
- **License:** MIT
- **Homepage:** https://bsky.app/profile/skywatch.blue

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-skywatch-bsky-skywatch-agent-skills-skywatch-working-the-queue
- Seller: https://agentstack.voostack.com/s/skywatch-bsky
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
