Skills

Catalog

A skill is the unit of work in Ultron. The registry ships 71 skills across 8 categories. Skills are grouped into 7 personas for the UI, addressable by slash command, and resolvable by a plain language router. Each skill declares its model tier, its turn budget, and the tools it is allowed to call.

Updated today

Browse all skills

Every skill has a permalink with the full description, example prompts, and a token-efficient markdown version for LLM consumers. 71 skills total, grouped by the agent that owns them.

SpecterAcquisition Unit

Outbound, prospect discovery, email sequences.

14 skills
VC Prospector

Find investors — VCs, angels, seed funds — for fundraising. Streams to CRM in 2-3 min.

Decision-Maker Prospector

Find buyer decision-makers (VPs, Heads, Directors, Founders) at target companies.

Hiring-Manager Prospector

Find people hiring for a role that signals buying intent for the user's product.

Google Maps Leads

Scrape brick-and-mortar businesses from Google Maps — dental clinics, gyms, restaurants, agencies.

Email — First Touch

Write the FIRST cold email — opener, body, single CTA. Seniority-aware (ATL strategic / BTL operational).

Email — Cold Sequence Follow-Ups

COLD sequence — emails 2, 3, and breakup. The prospect never replied to email 1. They don't know you yet.

Email — Re-Engagement

Win-back ghosted, lost, or churned prospects with a real 'what's new' angle.

Email — Subject Lines

5-8 subject-line variants tagged with formula, character count, and rationale.

Email — Batch Personalize

Apply ONE template across MANY leads with real per-lead specificity. Cap 30 per batch.

Lead Scoring

Score and prioritize existing leads on fit + engagement signals. Writes scores back to the CRM.

ICP Deep Match

Deep-evaluate whether a single company or lead matches the user's ICP — fit score + reasons.

Trigger Events

Find recent buying-trigger events (funding, hiring, launches) for target accounts.

Specter — Cold Outreach Campaign

End-to-end cold campaign — research prospects + craft a personalized cold sequence.

Specter — Lead Research & Enrichment

Find and enrich decision-makers at target companies. Builds a qualified prospect list.

SentinelEngineering Unit

Scaffold, clone, deploy, debug, audit.

15 skills
Spin up a Web App

Scaffold a fresh web app in /work, start the dev server, surface the live preview URL.

Clone a Website

Fire ultron-capture: spider the site, deploy a branded clone, surface the URL when ready.

Build an Agent

Spin up an autonomous agent on the agent-runtime satellite — try templates first, custom build only if no fit.

Deploy to Cloudflare

Ship the current /work to Pages, Workers, or Containers — then verify the live URL.

Push to GitHub

Initialize /work as a git repo, create the GitHub repo, push, return the URL.

Swap Page Sections

Reorder <section> blocks in a minified HTML file with byte-level safety.

Refactor Across Files

Multi-file string operations with quote and escape safety — uses bun -e, not sed.

Iterate Until Green

Pin a goal + verifiable check; loop attempt → test → diagnose → fix until the check exits 0.

Debug a CF Worker

Tail logs, decode CF exception codes (1101 uncaught, 1102 CPU), trace which boundary is failing.

Provision a Database

Spin up D1, R2, KV, Vectorize, Hyperdrive, Supabase, or Neon — and wire the binding/connection string.

Verify a Deployment

Hit the live URL, capture status code, screenshot the homepage — prove runtime works (deploy success is not).

Schedule a Workflow

Build a CF Workflow — multi-day durable orchestration with sleeps + retries that survive redeploys.

Website Audit

Lighthouse-style audit: perf, SEO, security, accessibility — driven by Playwright in the container.

TDD a Feature

Red → green → refactor. Failing test first, minimum-code to pass, refactor only after green.

Security Review

OWASP Top 10 walk against the codebase with concrete proof-of-concept exploits per finding.

Overview

At a glance
Skills
71 in the manifest, all with permalinks
Categories
8 (lead-gen, research, content, paid-ads, sales, legal, ops, engineering)
Personas
7 (Cortex, Specter, Striker, Pulse, Sentinel, Amplify, Counsel)
Model tiers
haiku, sonnet, opus (resolved to versioned model ids at runtime)
Manifest
src/lib/skills/registry.ts
Prompt files
One SKILL.md per skill, grouped by category
Engine
src/lib/skills/engine.ts
Max parallel runs
2 per host process

Every interaction worth running through a structured agent is a skill. The catalog is closed in the sense that the registry enumerates every skill statically; nothing is registered at runtime. This is deliberate. It keeps the routing table predictable, makes the tool allow-list auditable, and lets the activity feed surface a real name for every step the user sees.

Skills compose. A persona prompt can chain multiple skill invocations from inside one chat turn. The user sees a single conversation; the engine sees several skill runs threaded together, each with its own model tier, its own tool catalog, and its own turn budget.

Categories

The 8 categories partition the manifest. The category controls where the SKILL.md file lives on disk and how the catalog browser groups entries.

CategorySkill countExamples
lead-gen14vc-prospector, decision-maker-prospector, email-first-touch, gmaps-leads
research10competitive-analysis, signal-funding, signal-news, trend-feed, company-deep-dive
content9content-pulse, humanizer, content-hooks, brand-voice, linkedin-post
paid-ads8ads-campaign-setup, ads-audiences, ads-copy, ads-creative, ads-bidding
sales6cold-email, follow-up, objection-handler, striker-pre-call, striker-post-call
legal6contract-draft, contract-review, clause-library, contract-negotiate, contract-compare
ops2pipeline-review, morning-briefing
design1canvas-intelligence
Note
The 56-in-manifest number reflects what the engine can load today. The slash-command picker may surface additional pending skills that have prompts on disk but no manifest entry yet; those are filtered out before they reach the engine.

Personas

Each persona is a slash command, a system prompt, and a curated subset of the catalog. There is no Persona class; the term refers to a UI grouping plus a routing rule.

PersonaSlashUnitRoleApprox skills
Cortex/cortexIntelligence UnitHead of Intelligence10
Specter/specterAcquisition UnitHead of Acquisition12
Striker/strikerGrowth UnitHead of Growth4
Pulse/pulseMarketing UnitHead of Marketing9
Sentinel/sentinelEngineering UnitHead of Engineering13
Amplify/amplifyPaid Media UnitHead of Paid Media8
Counsel/legal /counselLegal UnitGeneral Counsel6
Tip
The Counsel persona accepts two slash commands. /legal is the everyday form; /counsel exists as an alias for context-heavy contract work. Both resolve to the same persona prompt.

How a skill is invoked

Three paths arrive at the same engine entry point. The path the user takes only changes how the skill gets selected.

  1. 01
    Slash command
    The chat handler regex-matches ^/(striker|specter|cortex|pulse|sentinel|legal|counsel|amplify)\s at the start of the message. The persona id scopes the discovery step to that persona's skill subset.
  2. 02
    Plain language router
    Without a slash command, the chat loop exposes the discover_capability tool to the model. Claude reads the user message, classifies the intent, and picks a skill id from the catalog.
  3. 03
    Skill as tool
    Any tool-calling turn can invoke run_skill directly with a known skill id. This is how one skill chains into another mid-run.
src/app/api/chat/v2/route.tsts
1858const agentMatch = message.match(
1859 /^\/(striker|specter|cortex|pulse|sentinel|legal|counsel|amplify)\s/i
1860)
1861const agentId = agentMatch ? agentMatch[1].toLowerCase() : null
1862// agentId scopes discover_capability to the persona's skill subset

The SkillMeta interface

One TypeScript interface describes every entry in the manifest. All fields except author, version, license, and tags are required.

src/lib/skills/types.tsts
14export interface SkillMeta {
15 id: string // kebab-case, unique
16 name: string // human label
17 category: SkillCategory // one of 8 categories
18 description: string // when to invoke this skill
19 tools: ToolName[] // allow-list of callable tools
20 model: string // 'haiku' | 'sonnet' | 'opus'
21 maxTurns: number // 3 to 12
22 author?: string
23 version?: string
24 license?: string
25 tags?: string[]
26}
Note
The description field is not the system prompt. It is the trigger blurb the discovery step reads when choosing a skill. The full prompt lives in SKILL.md next to the manifest entry.

Loading a skill

The manifest holds metadata. The prompt lives on disk. Loading a skill merges the two.

src/lib/skills/registry.tsts
723export function loadSkill(id: string): Skill {
724 const meta = SKILL_MANIFEST.find((s) => s.id === id)
725 if (!meta) throw new Error(`Skill not found in manifest: ${id}`)
726
727 const filePath = path.join(SKILLS_DIR, meta.category, id, "SKILL.md")
728 const raw = fs.readFileSync(filePath, "utf-8")
729 const { frontmatter, content } = parseFrontmatter(raw)
730
731 return {
732 ...meta,
733 name: frontmatter.name || meta.name,
734 description: frontmatter.description || meta.description,
735 content, // becomes the system prompt
736 }
737}

SKILL.md frontmatter

src/lib/skills/sales/striker-post-call/SKILL.mdyaml
1---
2name: striker-post-call
3description: "Use when the user wants to build a post-call deliverable..."
4tools: [web_search, web_search_multiple, scrape_url, lookup_leads, search_memory, save_memory]
5model: sonnet
6maxTurns: 12
7category: sales
8---
9
10# Striker post-call
11...full instruction prompt continues here...
Tip
Frontmatter duplicates the manifest entry on purpose. The manifest is the source of truth at runtime; the frontmatter is the source of truth when a human is reading the file. They should match. The loader prefers frontmatter for name and description, which makes a SKILL.md self-documenting without requiring a registry rebuild.

Execution engine

One function runs every skill. It resolves the model, assembles the tool catalog, drives the tool-calling loop, streams progress, and persists side effects.

src/lib/skills/engine.tsts
235export async function runSkillMission(params: {
236 skillId: string
237 objective: string
238 userId: string
239 workspaceCode: string
240 conversationContext?: string
241 onProgress?: SkillProgressCallback
242}): Promise<MissionResult>
src/lib/skills/engine.tsts
34const MODEL_MAP: Record<string, string> = {
35 haiku: "claude-haiku-4-5-20251001",
36 sonnet: "claude-sonnet-4-6",
37 opus: "claude-opus-4-6",
38}
39const MAX_CONCURRENT_SKILLS = 2
40const ANTHROPIC_TIMEOUT_MS = 180_000 // 3 min for deep work

On entry the engine waits for a concurrency slot, resolves the model id, builds the session context (user profile plus recent and key memories), loads the skill, filters the tool catalog by connected integrations, and starts the loop. Progress streams to the caller through a callback so the chat surface can render live activity. On completion the engine writes a memory entry summarizing the run and an activity log row so the agent activity sidebar has something to show.

Tool allow-list

A skill can only call tools that appear in its manifest. The engine enforces this twice: once when assembling the tool catalog and again when an integration is missing.

src/lib/skills/engine.tsts
345// 1. Union the skill's tools with the always-on system tools
346const requested = Array.from(new Set([...skill.tools, ...SYSTEM_TOOLS]))
347
348// 2. Filter out tools whose provider isn't connected for this user
349const connected = await fetchConnectedProviders(userId)
350const allowed = requested.filter((name) =>
351 toolPassesConnectionGate(name, connected)
352)
353
354// 3. Hand the filtered list to the model
355const tools = getToolDefinitions(allowed)
Warning
A tool absent from skill.tools is not just hidden, it is never serialized into the API call. The model has no way to call a tool that did not make it through both gates.

Concurrency and retry

The engine protects shared rate limits by capping parallel runs and backing off on 429s.

src/lib/skills/engine.tsts
87let _activeSkills = 0
88const _waitQueue: Array<() => void> = []
89
90async function acquireSlot(): Promise<void> {
91 if (_activeSkills < MAX_CONCURRENT_SKILLS) { _activeSkills++; return }
92 return new Promise<void>((resolve) => {
93 _waitQueue.push(() => { _activeSkills++; resolve() })
94 })
95}
src/lib/skills/engine.tsts
114async function fetchWithRetry(url: string, init: RequestInit, maxRetries = 2) {
115 for (let attempt = 0; attempt <= maxRetries; attempt++) {
116 const res = await fetch(url, init)
117 if (res.status === 429 && attempt < maxRetries) {
118 await sleep((attempt + 1) * 2000) // 2s, then 4s
119 continue
120 }
121 return res
122 }
123 return fetch(url, init)
124}

Example skills

A representative slice of the catalog showing how the metadata composes in practice.

SkillCategoryModelmaxTurnsTools (count)
competitive-analysisresearchhaiku86
signal-multi-aggregatorresearchsonnet85
email-first-touchlead-gensonnet66
ads-campaign-setuppaid-adssonnet84
contract-reviewlegalsonnet127
Tip
A high maxTurns like 12 on contract-review reflects the document scanning and citation pass the skill performs. A low maxTurns like 6 on email-first-touch reflects a tight outreach format that should not wander.

File map

src/lib/skills
registry.tsthe manifest plus loadSkill()
types.tsSkillMeta, SkillCategory, ToolName
engine.tsrunSkillMission, concurrency, retry
memory.tscontext cascade + auto-write on completion
research
competitive-analysis
SKILL.md
signal-funding
SKILL.md
trend-feed
SKILL.md
lead-gen
vc-prospector
SKILL.md
decision-maker-prospector
SKILL.md
email-first-touch
SKILL.md
sales
cold-email
SKILL.md
striker-post-call
SKILL.md
content
content-pulse
SKILL.md
humanizer
SKILL.md
paid-ads
ads-campaign-setup
SKILL.md
ads-creative
SKILL.md
legal
contract-review
SKILL.md
clause-library
SKILL.md
ops
morning-briefing
SKILL.md
pipeline-review
SKILL.md
design
canvas-intelligence
SKILL.md
src/app/api/chat/v2
route.tsslash command match, discovery, run_skill
src/components
ChatInterface.tsxpersona definitions and picker UI
AgentActivitySidebar.tsxlive skill activity feed

Glossary

Skill
A registered unit of work with a manifest entry, a SKILL.md prompt, a model tier, a turn budget, and a tool allow-list.
Manifest
The flat array SKILL_MANIFEST in registry.ts. The runtime source of truth for which skills exist.
SKILL.md
The markdown file on disk that carries the full system prompt for one skill. Loaded into the engine when the skill runs.
Category
One of eight folder names under src/lib/skills/. Determines where the SKILL.md lives and how the catalog groups.
Persona
A UI label and slash command that scopes skill discovery to a curated subset of the catalog. Not a runtime entity.
Tier
The model class declared on the skill (haiku, sonnet, opus). Resolved to a versioned model id by the engine.
Turn budget
maxTurns on the manifest. Hard cap on the number of tool-calling iterations the engine will run before forcing a final answer.
Discovery
The step in the chat loop that selects a skill from the catalog, either from a slash command or from a plain language classification.
Mission
One full execution of a skill from entry to completion. Tracked by activity log and summarized into agent memory.