← Corpus / augment-it / exploration
Agent-Chat Skills and Commands — Candidates List
The in-app chat surface (apps/chat) is augment-it's verb-routing layer — the place a user states a goal in prose and a capability handler executes it. Today's roster is small and prompt-focused: `prompts.draft`, `prompts.improve`, `prompts.apply`, `records.list`. The product needs many more verbs to be useful, and several scripts that already exist under `scripts/` and `services/*/scripts/` are the natural first candidates to graduate from shell-only into chat-callable capabilities. This doc maintains the running list of candidates — what they do, what shape they need to take (TS handler / ScriptCapability / McpCapability / SkillCapability), what gating they require (destructive vs read-only, scope-aware vs global), and what the chat-side phrasing should look like. Treated as a living roster — the next session adds entries as they get nominated; promotion out of this doc happens when a candidate becomes a spec or lands in `packages/workspace/src/capabilities/`.
- Path
- explorations/Agent-Chat-Skills-and-Commands-Candidates.md
- Authors
- Michael Staton
- Augmented with
- Claude Code on Claude Opus 4.7 (1M context)
- Tags
- Exploration · Augment-It · Agent-Chat · Capabilities · Verb-Surface · Skills · Commands · Living-Roster
Agent-Chat Skills and Commands — Candidates List
Why this list
The chat surface in apps/chat/ is augment-it’s verb-routing layer. A user says “draft a prompt that pulls each foundation’s mission statement” and the chat resolves that to prompts.draft, runs the handler, returns the result in a render-hint-shaped response. The current verb roster — four capabilities — is enough to demonstrate the gated-enhancement triad but nowhere near enough to be the user’s primary surface for the product.
There are also already-existing operations that today live as shell scripts and one-off TS files (scripts/backup-stores.sh, services/social-search/scripts/scrap-pack-artifacts.ts, the smoke-* scripts, the prompt-runner CLI flags), all of which are the kind of thing a user should be able to ask the chat to do in prose — but none of which the chat can currently invoke because no one has wrapped them as capabilities.
This doc keeps a running list of candidates: things the chat should be able to do, what shape the wrapper needs to take, and what gating concerns apply (destructive ops need explicit confirmation; scope-aware ops need a record-set parameter; etc.). It is not a spec for any one candidate — when a candidate is ready to build, fork a spec out of it and mark the entry here as “promoted out.”
How to read this doc
Each candidate has the same skeleton:
### <verb name>
- **What it does:** one-liner intent in user-prose
- **Today's shape:** where this lives currently (script path, code path, or "doesn't exist")
- **Proposed adapter:** TS handler | ScriptCapability | McpCapability | SkillCapability
- **Gating concerns:** destructive? scope-required? rate-limited? confirmation-required?
- **Suggested chat phrasing:** what the user would naturally say
- **Hand-off:** how the chat would surface the result (display_hint mount target, render mode)
- **Status:** Candidate | Scoping | Spec exists → <path> | Shipped
Adapter shapes are the four named in [[In-App-Chat-v0-0-1-for-Augment-It]]:
- TS handler — capability function lives in
packages/workspace/src/capabilities/<verb>.ts, runs in-process. Good for fast, deterministic ops that read shared types. - ScriptCapability — invokes a shell or node script via a templated command line. Good for ops that already exist as scripts (backup-stores, scrap-pack-artifacts) and would be unnecessarily expensive to reimplement.
- McpCapability — calls out to an MCP server (Chroma, future SearXNG, etc.). Good for ops backed by an external substrate with its own protocol.
- SkillCapability — invokes a packaged Lossless skill (the
lossless-skillsfamily). Good for ops that should also be runnable from outside augment-it.
Category 1 — Data safety
The triage cockpit accumulates a lot of carefully-edited data in responses.json / rows.json / prompts.json / sessions.json. Losing them by accident (a stack-down + volume prune, a malformed docker compose change, a regretted scrap script) wipes hours of human triage. Every destructive op in this category needs a confirmation gate.
data.backup
- What it does: Snapshot every JSON-file store into
.backups/<timestamp>/with a manifest (branch, head, commit msg). - Today’s shape:
scripts/backup-stores.sh(Bash, reads files viadocker cpfrom running containers). - Proposed adapter: ScriptCapability —
bash scripts/backup-stores.sh, captures stdout for the manifest summary. - Gating concerns: None on the way in (additive only). Should warn if any store container isn’t running.
- Suggested chat phrasing: “back up the stores”, “snapshot everything before the v4 promote”, “save what we have”
- Hand-off: Inline render-hint with the snapshot path + per-file byte counts + the “restore later with…” line.
- Status: Candidate. Nominated 2026-05-26 — the first concrete entry on this list.
data.restore
- What it does: Restore a named snapshot back into the running containers and restart them so re-reads happen cleanly.
- Today’s shape:
scripts/backup-stores.sh restore <stamp>. - Proposed adapter: ScriptCapability —
bash scripts/backup-stores.sh restore {{stamp}}. - Gating concerns: Destructive — overwrites live data. Must require an explicit confirmation turn (“yes, restore from 2026-05-26_014233”). Should refuse if no snapshot matches the stamp. Should ideally
data.backupfirst (snapshot-before-restore safety net) and announce that in the chat. - Suggested chat phrasing: “restore from the snapshot before the cleanup”, “roll back the stores to 2026-05-26 morning”
- Hand-off: Inline render-hint with the snapshot manifest preview before confirming, then a “restored — restart these containers” line.
- Status: Candidate (pair with
data.backup).
data.list_snapshots
- What it does: List every snapshot under
.backups/with its manifest summary (timestamp, branch, head, commit msg). - Today’s shape: Doesn’t exist as a single op (the user
ls .backups/andcat MANIFEST.txts individually). - Proposed adapter: TS handler — read
.backups/*/MANIFEST.txt, return a list. - Gating concerns: None (read-only).
- Suggested chat phrasing: “what backups do we have?”, “show me the snapshots from yesterday”
- Hand-off: Tabular render mode.
- Status: Candidate.
data.scrap_pack_artifacts
- What it does: Remove every pack response (
pack_id !== null) fromresponses.jsonand strip everyprofiles.*key fromrow.fieldsinrows.json. Used to clean up after a bad fan-out before the design pivoted to a singlesocialscolumn. - Today’s shape:
services/social-search/scripts/scrap-pack-artifacts.ts— idempotent,--dry-runflag, backs up first. - Proposed adapter: ScriptCapability —
tsx services/social-search/scripts/scrap-pack-artifacts.ts {{--dry-run?}}. - Gating concerns: Destructive. Should default to
--dry-runfrom chat and require an explicit “now actually do it” turn. Internal backup already happens; chat should announce the backup path. - Suggested chat phrasing: “clean up the bad pack artifacts”, “do a dry-run scrap of the v3 pack responses”
- Hand-off: Inline render-hint showing the dry-run counts (N responses to remove, M row writes to revert) before the confirm turn.
- Status: Candidate.
Category 2 — Inspection / status
Read-only verbs the user reaches for when orienting. None of these need gating; all should default to terse output that fits in a single chat reply.
records.list
- What it does: List record sets in the workspace (id, name, row count, created_at).
- Today’s shape: Shipped. TS handler at
packages/workspace/src/capabilities/records.list.ts. - Status: Shipped — Reference implementation for other inspection verbs.
records.show
- What it does: Show a single row’s full
row.fieldsmap (every key, every value, scalar OR JSON). - Today’s shape: Doesn’t exist as a capability; Record Collector renders this UI-side.
- Proposed adapter: TS handler — fetch row by id, return full fields map.
- Gating concerns: None.
- Suggested chat phrasing: “show me Bridgespan’s row”, “what do we have for row 42?”
- Hand-off: Inline render-hint pointing the user at Record Collector for inline editing.
- Status: Candidate.
responses.count_by_outcome
- What it does: Counts responses grouped by
outcome(found / not_found / error / skipped / pending), optionally scoped to a record set OR a pack OR a run. - Today’s shape: Doesn’t exist.
- Proposed adapter: TS handler — reads response-store via a new aggregation method.
- Gating concerns: None.
- Suggested chat phrasing: “how did common-seven do on the foundation set?”, “how many not_found from the bluesky pack?”
- Hand-off: Tabular render mode + a deep-link to Response Reviewer pre-filtered to the scope.
- Status: Candidate.
packs.list
- What it does: List every registered pack with its source, domain whitelist, and current connector.
- Today’s shape: Hardcoded in
services/social-search/src/packs.ts. - Proposed adapter: TS handler — re-export the PackConfig roster as a read-only view.
- Gating concerns: None.
- Suggested chat phrasing: “what packs do we have?”, “what’s the linkedin pack configured for?”
- Hand-off: Tabular render mode.
- Status: Candidate.
stack.status
- What it does: Report which services are running (docker compose ps mapped to friendly names + which API keys are present in .env).
- Today’s shape:
docker compose ps+ manual.envinspection. - Proposed adapter: ScriptCapability + small parse step → TS-shaped output.
- Gating concerns: None.
- Suggested chat phrasing: “is the stack up?”, “is social-search running?”
- Hand-off: Inline render-hint with one row per service.
- Status: Candidate.
Category 3 — Enrichment flow
The verbs that actually do work against rows. The four shipped today fall here; the cluster needs to grow as packs and bundles mature.
prompts.draft / prompts.improve / prompts.apply
- Status: Shipped (the v0.0.1 gated-enhancement triad).
packs.fire
- What it does: Fan out one or more packs across a row scope. The single-cell verb behind Pack Runner’s “Fire” button.
- Today’s shape: Wired as
pack.fan_out.requestedNATS subject; reached from Pack Runner UI but not from chat. - Proposed adapter: TS handler that wraps the existing NATS publish.
- Gating concerns: Expensive (cost-scales as
P packs × N rows). Chat should always preview the cell count before firing and require confirmation if total > some threshold (50? 100?). - Suggested chat phrasing: “fire common-seven against the foundation set”, “run linkedin + x for the rows missing LinkedIn”
- Hand-off: Inline render-hint with the cell-count preview, then once confirmed a deep-link to Pack Runner showing the live tally.
- Status: Candidate.
bundles.fire
- What it does: Fan out a bundle (a named roster of packs with orchestration + carry-forward + a chat verb). The blueprint’s
profile-builder.<entity-type>shape. - Today’s shape: Bundles don’t exist yet — the blueprint’s bundle sub-contracts are locked but no implementation has landed.
- Proposed adapter: TS handler that orchestrates pack.fan_out across passes per the bundle config.
- Gating concerns: Same as
packs.fire, but cell counts are higher because bundles include orchestration passes. - Suggested chat phrasing: “build profiles for these foundations”, “fire profile-builder.philanthropy against the v4 set”
- Hand-off: Pack Runner + Response Reviewer paired open.
- Status: Candidate — blocked on the first bundle existing.
pack.dedup_against_helpful_links
- What it does: Pre-flight agent-scan that checks existing
row.fields.helpful_linksfor URLs that already cover what a pack would search for, and marks those rows asskippedbefore fan-out. Saves Tavily cost. - Today’s shape: Doesn’t exist; sequenced in the [[Packs-and-Bundles-Pattern]] blueprint as the pre-flight dedup hook.
- Proposed adapter: TS handler invoked before
packs.fire(or wired as adedup: trueflag on the fan-out request). - Gating concerns: None on its own; integrates into the gating model of the verb that calls it.
- Status: Candidate — sequenced behind bundle work.
Category 4 — Record-set lifecycle
Promotion, archival, and the three-state row discipline (none / needs_clarification / archived).
records.promote
- What it does: Promote selected rows from a parent record set into a new canonical (vN+1) record set, applying the type-driven fold across responses + helpful_links + socials.
- Today’s shape: Shipped as UI behavior in Enhanced Records List; not yet a chat verb.
- Proposed adapter: TS handler that wraps the existing row-store promote logic.
- Gating concerns: Creates a new record set (additive, not destructive). Confirm the row scope before firing.
- Suggested chat phrasing: “promote the good rows to v4”, “create a new set from the foundations with verified LinkedIns”
- Hand-off: Deep-link to the new Enhanced Records List view.
- Status: Candidate.
records.archive_row / records.restore_archived
- What it does: Set / clear
row.fields.archivedon a row scope. Archived rows still exist (visible in Record Collector’s archived tab) but skip operations. - Today’s shape: UI behavior in Record Collector; not yet a chat verb.
- Proposed adapter: TS handler.
- Gating concerns: Reversible (restore exists), so light confirmation only.
- Suggested chat phrasing: “archive the rows where the foundation closed”, “un-archive everything from August”
- Status: Candidate.
records.flag_needs_clarification / records.clear_needs_clarification
- What it does: Set / clear
row.fields.needs_clarification: { reason, flagged_at, flagged_by }. Distinct from archived — these rows ARE carried through promotions, but operations skip them and the canonical CSV shows their enrichment columns as conscious gaps. - Today’s shape: Doesn’t exist; reserved key declared in design, not yet implemented.
- Proposed adapter: TS handler.
- Gating concerns: Reversible.
- Suggested chat phrasing: “flag the ambiguous foundations for the client”, “clear all clarification flags from the v4 set”
- Status: Candidate — blocked on Part 5 of [[Run-as-First-Class-Operation]].
Category 5 — Triage assist
Bulk-apply verbs that take the by-record triage work and let the user collapse N decisions into one chat turn.
responses.accept_by_confidence
- What it does: Accept every pack response with
confidence >= thresholdin a scope. Writes torow.fields.socials[]via the existing pack-fork in the accept handler. - Today’s shape: Doesn’t exist; today the user clicks accept per row in Response Reviewer.
- Proposed adapter: TS handler — iterates the response set, calls the existing
response.accept.requestedfor each match. - Gating concerns: Destructive in the sense that it writes to rows. Always preview the N-to-accept count before firing.
- Suggested chat phrasing: “accept every linkedin response above 80 confidence”, “accept all the wikipedia 100s”
- Hand-off: Inline render-hint with the count, then once confirmed a summary of how many landed on each row.
- Status: Candidate.
responses.bulk_flag
- What it does: Bulk-set the triage flag (good / wrong / partial / needs-human) across a filtered response set. The pattern that Response Reviewer renders per-row gets a chat-driven bulk path.
- Today’s shape: Doesn’t exist as a single op.
- Proposed adapter: TS handler.
- Gating concerns: Reversible (the user can re-flag).
- Suggested chat phrasing: “mark every not_found bluesky response as needs-human”, “flag the wikipedia disambiguation pages as wrong”
- Status: Candidate.
responses.retry_errors
- What it does: Re-fire every response whose outcome is
errorin a scope. - Today’s shape: Doesn’t exist; the renderer shows a disabled retry button per the structured-output extension changelog.
- Proposed adapter: TS handler that re-publishes the original
pack.search.requestedfor each. - Gating concerns: Expensive (re-runs Tavily). Confirm cell count.
- Status: Candidate.
Cross-cutting concerns
The destructive-op gating model
Several candidates above need confirmation before firing. The pattern should be uniform across all of them:
- User says the verb in prose (“restore from yesterday’s backup”)
- Chat resolves the verb, fetches the preview (snapshot manifest, cell count, row count, etc.)
- Chat replies with the preview + an explicit “Confirm by saying ‘yes’ or ‘do it’”
- User confirms in a follow-up turn
- Chat fires the actual op
This shape is not yet codified anywhere — it needs to land as part of whatever spec graduates the first destructive-op candidate (likely data.restore). Open question for the blueprint: should the confirmation turn be a chat convention, or should the capability layer expose a two-phase API (prepare → commit) that the chat orchestrates?
Scope resolution
Many verbs take a “scope” — a row scope, a record-set scope, a response scope. The chat should resolve a vague phrase (“the foundations”, “the v4 set”, “everything we did yesterday”) into a concrete scope before firing. Mechanism options:
- Lookup-by-name — chat fuzzy-matches the phrase against record-set names, pack names, run timestamps
- Anticipation hints — every verb declares what scope shapes it accepts; the chat shows a picker if the user’s phrase is ambiguous
- Carry-forward — once a scope is established in a conversation, subsequent verbs default to that scope (“now flag those as needs-human”)
Open question for the blueprint: which of these to land first, or all three with a precedence order?
The four adapter shapes and when to choose
Working rule of thumb based on the candidates above:
- TS handler — when the op is fast, deterministic, and operates on shared types already in
@augment-it/workspace. Most candidates above fit here. - ScriptCapability — when the op already exists as a shell or node script and rewriting it as a TS handler would just be translation. Specifically:
data.backup,data.restore,data.scrap_pack_artifacts,stack.status. - McpCapability — when the op needs an external substrate (Chroma for corpus search, SearXNG once that lands, etc.). No candidates above use this yet; the SearXNG migration introduces the first one.
- SkillCapability — when the op should also be runnable from outside augment-it (other AI products in the ai-labs tree, or via the Lossless
lossless-skillsdistribution). Candidate: the destructive-op gating discipline itself could be a skill; cross-cutting backup/restore patterns could too.
Promotion out of this list
When a candidate above is ready to build:
- Fork a spec under
context-v/specs/<verb>.md(or a plan undercontext-v/plans/if multi-phase). - Update the entry here to
Status: Spec exists → <path>(don’t delete; the candidate row remains the index entry). - Once the capability ships, update to
Status: Shippedwith a back-link to the changelog entry.
Entries that get rejected (the verb doesn’t make sense, the cost/value math doesn’t work, the use case dissolved on closer look) move to a §Rejected section at the bottom of this doc with a brief reason — keeping them visible so the next person doesn’t re-propose the same dead candidate.
Open questions to seed the next revision
- Q1. Should the destructive-op gating live in the capability layer (two-phase
prepare→commitAPI) or in the chat layer (a conversation convention)? — affects every destructive candidate above. - Q2. What’s the first bundle that lands, and does it gate the first
bundles.firechat verb on bundles existing at all? Currentlyprofile-builder.commonis the natural target (LinkedIn + X first, per the blueprint’s implementation order). - Q3. Should
responses.accept_by_confidencehonor only pack responses, or also legacy prompt responses (which don’t carry confidence — they’re prose)? Probably pack-only-by-shape; document the asymmetry. - Q4. How does the chat surface
display_hint.mount: <remote-id>deep-links — as a clickable card in the chat? aaugment-it:navigateevent dispatch? both? - Q5. What’s the right home for ScriptCapability adapters — alongside the script (
services/social-search/scripts/scrap-pack-artifacts.capability.tsnext to the .ts file) or centralized inpackages/workspace/src/capabilities/script-adapters/?
References
- [[In-App-Chat-v0-0-1-for-Augment-It]] — the plan that shipped the four-verb roster.
- [[Packs-and-Bundles-Pattern]] — the blueprint that defines packs, bundles, and the chat-verb registration sub-contract.
- [[Run-as-First-Class-Operation]] — Part 5 names
needs_clarificationas a reserved row key; blocks the corresponding chat verbs above. apps/chat/src/PromptDraftPanel.svelte— the reference implementation of how a capability result renders in chat.packages/workspace/src/capabilities/— where shipped TS-handler capabilities live.scripts/backup-stores.sh— the nominating script for this doc.services/social-search/scripts/scrap-pack-artifacts.ts— second ScriptCapability candidate already on disk.