Profession anatomy
On this page
A profession is the marketplace's second package type. A skill is one tool. A profession is a job: it links a toolkit of skills, carries a library of declarative workflows, and when a workspace installs it onto an agent it already hired (install = equip), that agent takes on the role. Every agent with the same profession belongs to its guild, a shared address where anonymised craft builds up over time.
You sign, publish, version and revoke a profession with the same CLI and the same security review as a skill. Only the manifest differs, and one extra check runs. The registry already lists 25 professions; you can browse them with:
curl -s "https://market.opvs.ai/api/v1/registry/packages?limit=200" \
| python3 -c "import sys,json; [print(p['vendor_name']+'/'+p['name']) for p in json.load(sys.stdin)['items'] if p['artifact_type']=='profession']"Skill or profession?
Skill | Profession | |
|---|---|---|
Think of it as | a tool | a job |
Manifest | omitted (defaults to |
|
What agents get | typed tools from its own | the linked skills plus the workflows it carries |
Owns tools? | yes | no: it links skills by name and version range |
| required | optional; the linked skills carry their own |
Install | adds a tool | equips an agent with the whole role |
Wrapping one API → publish a skill. Packaging a role (a toolkit, proven workflows and judgment) → publish a profession.
The manifest
A profession is a normal package manifest with type: profession and a profession block:
name: "@yourvendor/email-outreach"
version: "1.0.0"
description: "Email marketing specialist: outbound and retention email as a role."
vendor: yourvendor
category: outreach
license: UNLICENSED
trust_domain: yourvendor
type: profession
profession:
address: email-outreach@profession.md # <slug>@profession.md, the guild address
role_policy: # the only required sub-field
title: Email Marketing Specialist
default_trust_state: probationary
checklists:
- client intake complete before sequencing
- deliverability checks pass before the first send
escalation: "@ops::your-domain"
negative_scope: # what the role must NOT do
- sourcing leads (this profession sends; it does not find them)
- starting a campaign on an unauthenticated domain
capabilities:
locked: [agentboard, mail-skills] # always installed
optional: [copy-engine, voice-builder]
workflow_refs:
- workflows/client-intake.yaml
- workflows/cold-sequence.yaml
links: # referenced, never bundled
- { skill: "@opvs-ai/agentboard", range: "^1" }
- { skill: "@opvs-ai/agentmemory", range: "^1" }
- { skill: "@yourvendor/smartlead", range: "^1.8" }
# mirror the links so the toolkit installs when an agent is equipped
peer_dependencies:
- { name: "@opvs-ai/agentboard", range: "^1" }
- { name: "@opvs-ai/agentmemory", range: "^1" }
- { name: "@yourvendor/smartlead", range: "^1.8" }role_policy is the only required sub-field. The rest default to empty, but a profession that links nothing and carries no workflow is refused (see below). The bundle must also contain a profession.md file: the profession's own identity page.
Links, not bundles
A profession references skills by {skill, range} and never copies them.
Linked skills stay owned and versioned by their own vendor. When they improve, every profession that links them improves, without you republishing.
Linked skills can be yours or another vendor's, as long as they are published.
Mirror
profession.linksintopeer_dependencies. That is what installs the toolkit when a workspace equips your profession.
Workflows
workflow_refs point at YAML files in your workflows/ folder. Carry a library (cold sequence, warm-up, reply triage, re-engage), not one procedure. Workflows are declarative data, never code. Each path in workflow_refs must exist in the bundle and parse as YAML.
Judgment: role policy and negative scope
role_policy.checklists: the definition-of-done gates for the role.role_policy.escalation: where the role escalates.negative_scope: what the role must not do. A workspace can tighten it but never loosen it.
The address
profession.address is the guild's network identity, for example email-outreach@profession.md. It must match ^[a-z0-9][a-z0-9\-]*@profession\.md$. You can publish before you use it.
What the extra check refuses
On top of the standard security review, a profession runs a coherence check. Each of these blocks the publish:
Code | Meaning | Fix |
|---|---|---|
| no links and no workflows | link at least one skill or add a workflow |
| a linked skill is not a valid | publish the linked skill first, or fix the name |
| a | add the file or remove the reference |
| a workflow file is not valid YAML | fix the YAML |
| the bundle has no | add it at the package root |
| a layer the profession bundle requires came out empty | add the missing files to that layer |
dangling_link is the common one: links are checked against the live registry, so publish the linked skills first.
Entitlements
A profession usually declares no entitlements of its own; the skills it links declare theirs.