# V1 agent-architecture — pre-migration census (U1)

- Generated: 2026-04-24T10:11:40.306Z
- Usage signal: dev
- Catalog root: packages/skill-catalog/
- Repo: /Users/ericodom/Projects/thinkwork

Plan reference: `docs/plans/2026-04-23-007-feat-v1-agent-architecture-final-call-plan.md` §Implementation Units → U1.

This file is re-generated by `tsx packages/skill-catalog/scripts/census.ts`. Human edits are expected in the Bucket column and the Multi-entry decision column — in both cases promote the census's *proposed* verdict to a final one.

## Summary

| Slug | YAML execution | Mode | Entries | Multi-entry decision | scripts/ | references/ | Last commit (days) | Enabled rows | Tenants | Bucket |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| account-health-review | composition | tool | 0 | single-entrypoint | no | no | 2 | 0 | 0 | zero-rows-safe-swap |
| agent-email-send | script | reply | 1 | single-entrypoint | yes | no | 2 | 0 | 0 | zero-rows-safe-swap |
| agent-thread-management | script |  | 12 | indeterminate | yes | yes | 6 | 0 | 0 | zero-rows-safe-swap |
| artifacts | script |  | 3 | collapse-via-action-proposed | yes | no | 13 | 0 | 0 | zero-rows-safe-swap |
| compound | script | tool | 2 | explode-into-n-proposed | yes | no | 0 | 0 | 0 | zero-rows-safe-swap |
| customer-onboarding | context | tool | 0 | single-entrypoint | no | yes | 13 | 0 | 0 | zero-rows-safe-swap |
| customer-onboarding-reconciler | composition | tool | 0 | single-entrypoint | no | no | 0 | 0 | 0 | zero-rows-safe-swap |
| frame | context | tool | 0 | single-entrypoint | no | no | 0 | 0 | 0 | zero-rows-safe-swap |
| gather | declarative |  | 0 | single-entrypoint | no | no | 0 | 0 | 0 | zero-rows-safe-swap |
| google-calendar | script |  | 6 | collapse-via-action-proposed | yes | no | 10 | 0 | 0 | zero-rows-safe-swap |
| google-email | script |  | 5 | collapse-via-action-proposed | yes | no | 10 | 0 | 0 | zero-rows-safe-swap |
| task-system-tasks | context |  | 0 | single-entrypoint | no | yes | 6 | 0 | 0 | zero-rows-safe-swap |
| package | script | tool | 1 | single-entrypoint | yes | no | 0 | 0 | 0 | zero-rows-safe-swap |
| renewal-prep | composition | tool | 0 | single-entrypoint | no | no | 2 | 0 | 0 | zero-rows-safe-swap |
| sales-prep | composition | tool | 0 | single-entrypoint | no | no | 2 | 0 | 0 | zero-rows-safe-swap |
| sandbox-pilot | script |  | 1 | single-entrypoint | yes | no | 0 | 0 | 0 | zero-rows-safe-swap |
| skill-dispatcher | script | tool | 2 | collapse-via-action-proposed | yes | no | 0 | 0 | 0 | zero-rows-safe-swap |
| smoke-package-only | composition | tool | 0 | single-entrypoint | no | no | 1 | 0 | 0 | zero-rows-safe-swap |
| synthesize | context | tool | 0 | single-entrypoint | no | no | 0 | 0 | 0 | zero-rows-safe-swap |
| web-search | script |  | 3 | collapse-via-action-proposed | yes | no | 11 | 4 | 1 | low-rows-notify |
| workspace-memory | script |  | 3 | collapse-via-action-proposed | yes | no | 13 | 0 | 0 | zero-rows-safe-swap |

### Bucket totals

- **low-rows-notify**: 1
- **zero-rows-safe-swap**: 20

## Per-slug detail

### account-health-review

- Path: `packages/skill-catalog/account-health-review`
- YAML `execution`: `composition`, mode: `tool`
- Description: Periodic review of a customer account's health signals — engagement, usage, support load, financial posture. Produces a health report CSMs and AEs can skim ahead of a standing check-in.
- `scripts/`: no
- `references/`: no
- Last commit under dir: 2 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=0, multi-entry=single-entrypoint

### agent-email-send

- Path: `packages/skill-catalog/agent-email-send`
- YAML `execution`: `script`, mode: `reply`
- Description: Send emails from your agent email address with reply tracking. Use when the agent needs to send an email, reply, or follow up.
- `scripts/`: yes
- `references/`: no
- `requires_env`: THINKWORK_API_URL, THINKWORK_API_SECRET, AGENT_ID, AGENT_EMAIL_ADDRESS, INBOUND_MESSAGE_ID, INBOUND_SUBJECT, INBOUND_FROM, INBOUND_BODY
- Last commit under dir: 2 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=1, multi-entry=single-entrypoint

**`scripts[]` entries:**

- `send_email` → `scripts/send.py` — Send an email from the agent email address

### agent-thread-management

- Path: `packages/skill-catalog/agent-thread-management`
- YAML `execution`: `script`
- Description: Create sub-threads, manage dependencies, update status, and query threads. Use when breaking work into subtasks, tracking progress, or managing task dependencies.
- `scripts/`: yes
- `references/`: yes
- `requires_env`: THINKWORK_API_URL, THINKWORK_API_SECRET, AGENT_ID, TENANT_ID, CURRENT_THREAD_ID, CURRENT_USER_EMAIL
- Last commit under dir: 6 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=12, multi-entry=indeterminate

**`scripts[]` entries:**

- `create_sub_thread` → `scripts/threads.py` — Create a sub-thread under the current or specified parent thread
- `add_dependency` → `scripts/threads.py` — Block a thread until another completes
- `update_thread_status` → `scripts/threads.py` — Update thread status, channel, title, description, priority, due date, and assignee. Use channel=TASK to promote a chat to a task.
- `add_comment` → `scripts/threads.py` — Add a comment to a thread
- `list_sub_threads` → `scripts/threads.py` — List sub-threads with optional status filter
- `get_thread_details` → `scripts/threads.py` — Get full thread details including comments and dependencies
- `escalate_thread` → `scripts/threads.py` — Escalate a thread to the supervisor agent
- `delegate_thread` → `scripts/threads.py` — Delegate a thread to another agent
- `promote_to_task` → `scripts/threads.py` — Promote the current thread to a task — sets channel to TASK with metadata
- `search_users` → `scripts/threads.py` — Search tenant users by name or email for task assignment
- `schedule_followup` → `scripts/threads.py` — Schedule a future agent wakeup to follow up on tasks or deadlines
- `present_form` → `scripts/forms.py` — Render a Question Card form for the user to fill out. Pass form_path (skill-relative, e.g. 'customer-onboarding/references/intake-form.json') and an optional prefill_json string with any values you can extract from the conversation. The user submits and the next user message contains a ```form_response fenced block with all values.

### artifacts

- Path: `packages/skill-catalog/artifacts`
- YAML `execution`: `script`
- Description: Create and manage durable markdown-first artifacts. Use when the user asks to create a document, report, summary, or any persistent content.
- `scripts/`: yes
- `references/`: no
- Last commit under dir: 13 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=3, multi-entry=collapse-via-action-proposed

**`scripts[]` entries:**

- `create_artifact` → `scripts/artifacts.py` — Create a durable markdown artifact
- `update_artifact` → `scripts/artifacts.py` — Update an existing artifact
- `list_artifacts` → `scripts/artifacts.py` — List artifacts with optional filters

### compound

- Path: `packages/skill-catalog/compound`
- YAML `execution`: `script`, mode: `tool`
- Description: Learnings loop for compositions. `compound_recall` retrieves prior observations scoped to (tenant, user, skill, optional subject) at run start; `compound_reflect` extracts up to 3 new observations from the completed run and stores them under the same scope. Paired — edit docstrings together.
- `scripts/`: yes
- `references/`: no
- `requires_env`: AGENTCORE_MEMORY_ID
- Last commit under dir: 0 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=2, multi-entry=explode-into-n-proposed

**`scripts[]` entries:**

- `compound_recall` → `scripts/recall.py` — Retrieve top-K prior learnings for this composition run (user-scoped before tenant-scoped).
- `compound_reflect` → `scripts/reflect.py` — Extract up to 3 non-obvious observations from the completed run and store them under the composition's scope.

### customer-onboarding

- Path: `packages/skill-catalog/customer-onboarding`
- YAML `execution`: `context`, mode: `tool`
- Description: Onboard a new customer by gathering information and creating tasks for the team. Handles intake questions, conditional task creation, user assignment, and deadline tracking.
- `scripts/`: no
- `references/`: yes
- Last commit under dir: 13 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=0, multi-entry=single-entrypoint

### customer-onboarding-reconciler

- Path: `packages/skill-catalog/customer-onboarding-reconciler`
- YAML `execution`: `composition`, mode: `tool`
- Description: Drive a new customer from deal-close to onboarded by continuously reconciling desired state against actual state. Invoked via webhook on opportunity-won and re-invoked on task completions. Never blocks waiting for human input — each tick reads current state, creates the tasks that are still missing, and exits. HITL happens between ticks, not inside a single invocation.
- `scripts/`: no
- `references/`: no
- Last commit under dir: 0 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=0, multi-entry=single-entrypoint

### frame

- Path: `packages/skill-catalog/frame`
- YAML `execution`: `context`, mode: `tool`
- Description: Restate a problem in a structured way before gathering data. Returns goal, constraints, known unknowns, and decision criteria so downstream steps have a clean target. Composition-only primitive — not intended for direct chat use.
- `scripts/`: no
- `references/`: no
- Last commit under dir: 0 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=0, multi-entry=single-entrypoint

### gather

- Path: `packages/skill-catalog/gather`
- YAML `execution`: `declarative`
- Description: Parallel fan-out primitive. Not a runnable skill on its own — compositions declare a parallel step and the composition runner executes the branches concurrently. This entry exists so admins can see gather in the catalog alongside the other composition primitives.
- `scripts/`: no
- `references/`: no
- Last commit under dir: 0 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=0, multi-entry=single-entrypoint

### google-calendar

- Path: `packages/skill-catalog/google-calendar`
- YAML `execution`: `script`
- Description: Read events, check availability, create tentative events via Google Calendar API. Use when the user asks about calendar, schedule, or availability.
- `scripts/`: yes
- `references/`: no
- `requires_env`: GCAL_ACCESS_TOKEN, THINKWORK_API_URL, THINKWORK_API_SECRET, GCAL_CONNECTION_ID
- `oauth_provider`: google_productivity
- Last commit under dir: 10 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=6, multi-entry=collapse-via-action-proposed

**`scripts[]` entries:**

- `gcal_list_events` → `scripts/gcal.py` — List calendar events in a time range
- `gcal_get_event` → `scripts/gcal.py` — Get full details of a calendar event
- `gcal_check_availability` → `scripts/gcal.py` — Check free/busy status for a time range
- `gcal_create_event` → `scripts/gcal.py` — Create a tentative calendar event
- `gcal_update_event` → `scripts/gcal.py` — Update or confirm a calendar event
- `gcal_delete_event` → `scripts/gcal.py` — Delete a calendar event

### google-email

- Path: `packages/skill-catalog/google-email`
- YAML `execution`: `script`
- Description: Read inbox, triage messages, draft replies via Gmail API. Use when the user asks about email, inbox, or Gmail.
- `scripts/`: yes
- `references/`: no
- `requires_env`: GMAIL_ACCESS_TOKEN, THINKWORK_API_URL, THINKWORK_API_SECRET, GMAIL_CONNECTION_ID
- `oauth_provider`: google_productivity
- Last commit under dir: 10 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=5, multi-entry=collapse-via-action-proposed

**`scripts[]` entries:**

- `gmail_list_messages` → `scripts/gmail.py` — List messages in the Gmail inbox
- `gmail_get_message` → `scripts/gmail.py` — Get full details of a Gmail message
- `gmail_search_messages` → `scripts/gmail.py` — Search Gmail with query syntax
- `gmail_modify_labels` → `scripts/gmail.py` — Add or remove labels on a message (archive, mark read, etc)
- `gmail_create_draft` → `scripts/gmail.py` — Create a Gmail draft (user reviews and sends)

### task-system-tasks

- Path: `packages/skill-catalog/task-system-tasks`
- YAML `execution`: `context`
- Description: Collect intake details for a new external provider task via a Question Card form, then hand off to the external provider MCP's workflow_task_create tool. Use on user-created task threads where the external task hasn't been minted yet (sync_status='local').
- `scripts/`: no
- `references/`: yes
- Last commit under dir: 6 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=0, multi-entry=single-entrypoint

### package

- Path: `packages/skill-catalog/package`
- YAML `execution`: `script`, mode: `tool`
- Description: Render a synthesis into a final deliverable using a named template. Deterministic — template substitution only, no LLM call at this step. Supported formats in v1 are sales_brief, health_report, and renewal_risk.
- `scripts/`: yes
- `references/`: no
- Last commit under dir: 0 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=1, multi-entry=single-entrypoint

**`scripts[]` entries:**

- `render_package` → `scripts/render.py` — Render a synthesis dict into a Markdown deliverable using a named template.

### renewal-prep

- Path: `packages/skill-catalog/renewal-prep`
- YAML `execution`: `composition`, mode: `tool`
- Description: Prep a customer renewal conversation. Pulls contract terms, recent usage, support posture, renewal history, and win/loss signals, then renders a renewal_risk brief ordered by deal-impact likelihood.
- `scripts/`: no
- `references/`: no
- Last commit under dir: 2 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=0, multi-entry=single-entrypoint

### sales-prep

- Path: `packages/skill-catalog/sales-prep`
- YAML `execution`: `composition`, mode: `tool`
- Description: Gather account context, financials, activity, and external signals for a sales meeting. Produces a packaged brief the rep can read in 60 seconds.
- `scripts/`: no
- `references/`: no
- Last commit under dir: 2 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=0, multi-entry=single-entrypoint

### sandbox-pilot

- Path: `packages/skill-catalog/sandbox-pilot`
- YAML `execution`: `script`
- Description: Reference template exercising the full AgentCore Code Sandbox path — pulls skill_runs from Thinkwork's GraphQL, summarises them with pandas via execute_code, and uploads a chart to S3 using the sandbox's per-tenant IAM role. Use for dogfood validation when onboarding a new tenant to the sandbox substrate.
- `scripts/`: yes
- `references/`: no
- `requires_env`: THINKWORK_API_URL, THINKWORK_API_SECRET
- Last commit under dir: 0 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=1, multi-entry=single-entrypoint

**`scripts[]` entries:**

- `run_pilot` → `scripts/pilot.py` — Runs the sandbox-pilot flagship demo end-to-end.

### skill-dispatcher

- Path: `packages/skill-catalog/skill-dispatcher`
- YAML `execution`: `script`, mode: `tool`
- Description: Chat intent router for composition skills. When the user asks for something that matches a registered composition (sales prep, account health review, renewal prep, etc.), call start_composition to kick off the run. Do NOT use this for single-tool skills — invoke those directly.
- `scripts/`: yes
- `references/`: no
- `requires_env`: THINKWORK_API_URL, THINKWORK_API_SECRET, TENANT_ID, CURRENT_USER_ID
- Last commit under dir: 0 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=2, multi-entry=collapse-via-action-proposed

**`scripts[]` entries:**

- `start_composition` → `scripts/dispatch.py` — Start a composition skill run for the current user with resolved inputs. Returns runId + status.
- `composition_status` → `scripts/dispatch.py` — Fetch the status of a previously-started composition run by runId. Returns status, started_at, finished_at, delivered_artifact_ref.

### smoke-package-only

- Path: `packages/skill-catalog/smoke-package-only`
- YAML `execution`: `composition`, mode: `tool`
- Description: End-to-end smoke for the composable-skill dispatch path. A one-step composition that calls the deterministic `package` script skill, no LLM, no external connectors. Exists solely so that a `/api/skills/start` + agentcore run → `skill_runs.status='complete'` transition can be proved end-to-end against the deployed stack.
- `scripts/`: no
- `references/`: no
- Last commit under dir: 1 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=0, multi-entry=single-entrypoint

### synthesize

- Path: `packages/skill-catalog/synthesize`
- YAML `execution`: `context`, mode: `tool`
- Description: Read a frame + gathered data (and optionally prior learnings) and produce a structured analysis — risks, opportunities, open questions, and talking points — that the package step will render into a deliverable. Composition-only primitive.
- `scripts/`: no
- `references/`: no
- Last commit under dir: 0 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=0, multi-entry=single-entrypoint

### web-search

- Path: `packages/skill-catalog/web-search`
- YAML `execution`: `script`
- Description: Search the web, read pages, and research companies. Provider-agnostic — backed by Exa or SerpAPI depending on tenant configuration. Use when the user needs current information, wants to look something up, or asks about a company.
- `scripts/`: yes
- `references/`: no
- `requires_env`: WEB_SEARCH_PROVIDER, EXA_API_KEY, SERPAPI_KEY
- Last commit under dir: 11 days ago
- `agent_skills` (dev): 4 enabled rows across 1 tenants
- Verdict: **low-rows-notify**, entries=3, multi-entry=collapse-via-action-proposed

**`scripts[]` entries:**

- `web_search` → `scripts/search.py` — Search the web for current information
- `web_read` → `scripts/search.py` — Read the full text content of web pages
- `company_research` → `scripts/search.py` — Research a company — profile, news, people, databases

> notify 1 tenant(s) (4 enabled rows) before rename or cutover

### workspace-memory

- Path: `packages/skill-catalog/workspace-memory`
- YAML `execution`: `script`
- Description: Read, write, and list workspace memory files (S3-backed). Use when the agent needs to remember information between conversations.
- `scripts/`: yes
- `references/`: no
- `requires_env`: WORKSPACE_BUCKET, TENANT_ID, AGENT_ID
- Last commit under dir: 13 days ago
- `agent_skills` (dev): 0 enabled rows across 0 tenants
- Verdict: **zero-rows-safe-swap**, entries=3, multi-entry=collapse-via-action-proposed

**`scripts[]` entries:**

- `workspace_memory_write` → `scripts/memory.py` — Write a structured note to workspace memory
- `workspace_memory_read` → `scripts/memory.py` — Read a file from workspace memory
- `workspace_memory_list` → `scripts/memory.py` — List all files in workspace memory

## Staging / prod SQL

The census only auto-queries the database when `DATABASE_URL` is set (typically dev via `scripts/db-push.sh --stage dev` resolution). Run the SQL below against staging and prod, paste the result back into this file under 'Per-slug detail', and re-bucket accordingly.

```sql
-- agent_skills usage probe, generated by packages/skill-catalog/scripts/census.ts
-- Run against staging and prod; paste counts back into the census markdown.
select
  skill_id,
  count(*)                         as enabled_rows,
  count(distinct tenant_id)        as tenants,
  min(created_at)                  as first_enabled_at,
  max(created_at)                  as latest_enabled_at
from agent_skills
where enabled = true
  and skill_id in ('account-health-review', 'agent-email-send', 'agent-thread-management', 'artifacts', 'compound', 'customer-onboarding', 'customer-onboarding-reconciler', 'frame', 'gather', 'google-calendar', 'google-email', 'task-system-tasks', 'package', 'renewal-prep', 'sales-prep', 'sandbox-pilot', 'skill-dispatcher', 'smoke-package-only', 'synthesize', 'web-search', 'workspace-memory')
group by skill_id
order by enabled_rows desc, skill_id;
```

## Operational notes

- **Retirement-candidate promotion:** for every slug marked `retirement-candidate-pending-signoff`, check `gh issue list --search "<slug>" --state open` and obtain written feature-owner sign-off before editing the bucket to `retirement-candidate` in this file and the follow-up PR.
- **`needs-explicit-migration`:** census never sets this automatically. Set it on a slug during review when you've decided to rename (e.g., a new canonical slug coexists alongside the old slug suffixed `-legacy`).
- **Multi-entry decisions:** the `*-proposed` suffix means the heuristic (shared vs. distinct `scripts[].path`) picked a direction; confirm or flip during U8 per-slug PRs.

### `thinkwork-admin` (planned, not yet merged to main)

The V1 plan references `thinkwork-admin` with 33 script entries as the largest
multi-entrypoint example. As of this census it lives only under
`.claude/worktrees/shared-admin-ops-brainstorm/packages/skill-catalog/thinkwork-admin/`
and is not in `main`. Re-run the census after that worktree's PR merges; expect a new
row with `multi-entry-decision` either `collapse-via-action-proposed` (if all 33
entries share one `scripts[].path`) or `explode-into-n-proposed` (if each has its own).
