Skip to main content
The marketplace ships an in-bundle catalog of 304 agents and 82 teams. Every entry is a committed TypeScript literal, and the catalog is browsed and deployed entirely client-side: no API call, no external service, works fully offline. It is code-split — the ~4.4 MB of catalog data compiles into its own marketplace-catalog chunk that the app fetches from its own static assets the first time you open the Marketplace or create a team, so a dashboard load that touches neither never pays for it. Two of the agent sources (agency-agents, awesome-openclaw) and three of the team files are codegen’d from pinned upstream commits by scripts/ingest-marketplace-content.ts; the rest are hand-written. An offline CI gate (pnpm verify:catalog) checks the committed files against a committed integrity manifest, and a live check (pnpm verify:ingest) re-derives them from upstream on a weekly schedule. This page documents the schemas (AgentCatalogEntry, TeamTemplate), the ID prefix convention, the zero-loss identityTemplate invariant, the three sources + their pinned SHAs, and the ingestion mechanism. It does not enumerate individual entries; browse those in the marketplace UI (the Agents / Teams tabs) or read the committed files under apps/web/src/features/marketplace/.

At a glance

The catalog ships 304 agents and 82 teams. The unit tests assert lower bounds (>= 270 agents, >= 160 agency, >= 40 awesome, >= 15 clawboo) rather than exact counts, so an upstream re-ingest can grow the catalog without breaking tests.

AgentCatalogEntry

The first-class catalog entry for a single deployable agent. Defined in apps/web/src/features/teams/types.ts. Every entry across all three sources conforms to this shape.
AgentDomain is a 15-value union: academic, design, engineering, game-development, marketing, paid-media, product, project-management, sales, spatial-computing, specialized, support, testing (the 13 agency domains), plus openclaw (awesome-openclaw entries) and clawboo (built-ins). TemplateCategory is an 18-value union: engineering, marketing, sales, product, design, testing, content, support, education, ops, devops, research, game-dev, spatial, academic, paid-media, specialized, general.

The four deploy artifacts

The four template fields map one-to-one onto the four agent files written when an agent is deployed:

TeamTemplate

A deployable team, metadata plus a list of catalog agent ids. Defined in apps/web/src/features/teams/types.ts. First-party teams reference agents by agentIds (the inline agents array is a deprecated back-compat path kept only so hypothetical user-defined templates still type-check).

Resolving a team into deployable agents

resolveTeamAgents(profile) (in teamCatalog.ts) is the single consumer-facing resolver. For a first-party TeamTemplate it walks agentIds, looks each one up in AGENT_CATALOG, and returns a ResolvedAgent[] carrying the full soulTemplate / identityTemplate / toolsTemplate and the team-specific agentsTemplate (from team.routing[agentId], falling back to the agent’s own agentsTemplate). A dangling id is silently skipped; teamCoverage.test.ts guards against that. The resolver also handles two legacy input shapes (inline agents, and the deprecated TeamProfile with shared skills[]).
Hub-and-spoke routing for codegen’d teams is generated at ingest time: the first agent in agentIds is the leader, every other member routes work to @<Leader>, and the leader’s AGENTS.md lists all members. This is what produces the dependency edges visible in the Ghost Graph after a team deploys.

ID prefix convention

Every agent id is globally unique across sources, and its prefix encodes the source. This is enforced by agentCatalog.test.ts (all ids unique; prefix matches source). Team ids follow source-specific patterns (e.g. agency-workflow-startup-mvp, awesome-<usecaseSlug>, <domain>-excellence-<n>) but are not prefix-constrained the way agent ids are.

Zero-loss identityTemplate invariant

The defining property of the catalog: every entry’s identityTemplate is the full, verbatim source content, never a condensed summary. For the two upstream sources it is the exact .md file body fetched at the pinned commit; for clawboo built-ins it is a synthesized manifest combining role + soul + identity + tools + routing under headings. soulTemplate is the shorter distilled version written to SOUL.md. The hard guarantee, asserted for every entry by agentCatalog.test.ts:
This is what lets the agent-detail modal render the entire original spec before deploy, and what makes a deploy lossless; IDENTITY.md receives the source content byte-for-byte (clawboo built-ins receive the synthesized manifest, which is structured around the original fields, not lossy of them).

Sources

The catalog draws from three sources, all MIT-licensed and (for the two upstream repos) pinned to a fixed commit so ingestion is deterministic. Attribution lives in THIRD_PARTY_NOTICES.md. The pinned SHAs are constants in scripts/lib/ingest-helpers.ts (AGENCY_AGENTS_SHA, AWESOME_OPENCLAW_SHA); both the ingest and verify scripts import them, and every generated entry’s sourceUrl is a GitHub blob URL at the pinned commit.

agency-agents (179 agents)

13 domain .md collections fetched from the repo tree at the pinned SHA, one committed file per domain under agents/agency/: agents/agency/index.ts concatenates all 13 arrays into AGENCY_AGENTS.

awesome-openclaw (110 agents)

110 entries extracted from 42 usecase .md files: a guaranteed per-usecase *-operator entry (42), plus named role/phase agents parsed from each usecase body (68). The named-agent extraction runs five regex passes over each file (### Agent N: Name (Role), ### Name Agent, **Name Agent** bold, and two passes scoped to the ## What It Does section), de-duped per file by role slug. All entries land in agents/awesome-openclaw/usecases.ts (exported AWESOME_OPENCLAW_USECASES), re-exported as AWESOME_OPENCLAW_AGENTS.

clawboo built-ins (15 agents)

15 first-class agents, synthesized at import time (not literal id: strings in a generated file). agents/clawboo/builtin.ts is hand-written: it imports the five built-in TeamTemplate literals from agents/clawboo/sources/{dev,marketing,research,student,youtube}.ts and runs each team’s three inline AgentTemplates through fromInlineAgent(), which:
  • mints id = clawboo-<teamId>-<slug(agentName)>,
  • preserves name / role / soulTemplate / toolsTemplate / agentsTemplate verbatim,
  • synthesizes identityTemplate from the full set of fields under headings (so length > 500 holds), and
  • extracts skillIds, filtered against SKILL_CATALOG so only real catalog skill ids survive.
The result is exported as CLAWBOO_BUILTIN_AGENTSCLAWBOO_AGENTS. This file is hand-written because the source is local TS with path-alias imports the ingest script cannot resolve, so it is not covered by either gate (verify:catalog or verify:ingest).

Teams (82)

The 30 synthetic “Excellence Teams” exist so that every agency agent appears in at least one team; the ingest script excludes workflow-covered agents, then partitions the remainder into per-domain clusters. teams/index.ts concatenates all four arrays into TEAM_CATALOG (it is hand-written and not verified, but the three generated arrays it imports are).

Ingestion mechanism

The catalog is committed codegen, not a runtime fetch, and not hand-maintained line-by-line. The chosen trade-off: a runtime fetch would break offline-first installs; hand-writing ~300-line entries × hundreds of agents is error-prone; committed codegen is auditable in PR diffs and reproducible.

Regenerate

The script fetches both repos’ git trees at the pinned SHAs, downloads the raw .md files (concurrency 10), processes each into entries, and writes codegen’d files: 13 agency domain files + agency/index.ts + awesome-openclaw/usecases.ts + awesome-openclaw/index.ts + agents/index.ts, plus the three team files (agency-workflows.ts, awesome-openclaw.ts, synthetic.ts). Every write goes through a writeFormatted() helper that runs Prettier before flushing; without it the raw renderers emit double-quoted single-line strings that would drift against the committed files. As its final step the script writes scripts/ingest-manifest.json, recording the two pinned SHAs plus a sha256 per generated file. The clawboo built-ins (agents/clawboo/*), teams/clawboo-builtin.ts, and teams/index.ts are not part of the ingest pipeline; they are hand-written.

Verify (the two gates)

verify-catalog.ts is offline. It re-hashes each committed file and compares against scripts/ingest-manifest.json, also asserting that the manifest’s recorded SHAs still match the constants in ingest-helpers.ts and that it covers exactly the generated file set. Hashes are taken over each file’s Prettier canonical form, which makes them invariant to code style and to CRLF line endings. verify-ingest.ts is the live check. It re-runs the same render pipeline in memory against the pinned upstream commits, normalizes both sides through Prettier, and compares — exiting 1 on any mismatch with a short line diff. Hand-written files are skipped by both. Where they run:
  • ci.yml: a verify-catalog job, parallel to lint / typecheck / test / build. Drift turns the PR red.
  • publish.yml: a pnpm verify:catalog step before pnpm build. Drift blocks releases. Offline by design — an upstream rename or force-push (a non-retryable 404) must never be able to hold up a release.
  • verify-ingest.yml: verify:catalog then verify:ingest, on a weekly cron, on workflow_dispatch, and on PRs touching the ingest scripts or generated catalog.
The ingest renderers and the verifier share the logic in scripts/lib/ingest-helpers.ts, which removes most of the room for drift — but not all of it: renderAgentsIndex() is deliberately duplicated into verify-ingest.ts to keep the verifier self-contained, so the two copies can diverge. Running the live check is what detects that, which is why verify-ingest.yml triggers on any PR touching the ingest scripts. verify-ingest.ts additionally cross-checks its file list against the catalogFilePaths() enumeration the manifest is built from.
Generated catalog files carry an // AUTO-GENERATED — do not edit manually header. Editing one by hand is caught immediately and offline by verify:catalog. To change catalog content, bump the pinned SHA in scripts/lib/ingest-helpers.ts and re-run pnpm ingest:marketplace — see the refresh runbook.

See also

Last modified on August 7, 2026