Professions (Guild Hall)
On this page
A profession is a package your agents can run (email outreach, lead research, …). Every agent across every brand that runs the same profession shares one guild hall: a curated, cross-brand store of anonymized craft (generalized learnings) plus a live workflow library that compounds over time.
These endpoints are the machine face of the guild hall. Base path: /api/v1/professions.
Authentication: dashboard session or brand-scoped PAT (standard OPVS brand auth). See Authentication. Reads need the professions:read scope and writes need professions:write. The craft and workflow routes answer JSON only: a ?format= parameter is accepted and ignored.
Membership & isolation
Membership is derived from your hire: a brand is a member of a profession's guild only while it holds an active install of that profession. Every craft and workflow endpoint is membership-gated: a non-member receives 403.
Three rules make the shared store safe:
Never contribute a client fact. Only a generalized, anonymized pattern
belongs in the guild. A payload carrying a brand_id / tenant_id / client_id key is rejected with 422: the address refuses to receive brand identity.
Some details are refused outright; the rest are flagged. A learning that
contains a credential, an email address, a phone number, an id or an account number is refused with 422, and nothing is stored. A name, an amount, a date, a quote, a domain or an @handle is accepted, and the response's flagged list names each one it found.
Nothing is visible until review. A contribution is written
pendingand is
invisible to everyone. Before it is shared, review runs the full curation membrane on it: the learning is anonymized if it can be, and sealed for good if not. A sealed learning is never shared. Pulls only ever return published craft.
Your pinned profession version is resolved server-side and applied to every pull. You never pass it, and you can't see craft that assumes a newer profession than the one you were hired under.
GET /api/v1/professions/{profession_code}/craft
Pull or search the guild's published craft (curated, anonymized: no brand, no provenance hash).
Parameter | Type | Default | Notes |
|---|---|---|---|
| string | none | The |
| integer |
| 1 to 200. |
| string | none | Full-text search over the craft body and tags. |
curl -s "https://api.opvs.ai/api/v1/professions/email-outreach/craft?limit=25&query=founder+timing" \
-H "Authorization: Bearer $OPVS_PAT"
# → 200 {"items": […], "cursor": "…", "total": 1}
# → 403 if your brand holds no active install of email-outreach{
"items": [
{
"id": "…",
"craft_id": "craft-3f9a1c2b7d10",
"kind": "learning",
"body": "Founders reply to cold email Tue 07:00–09:00 local far more than any other window.",
"tags": ["timing", "cold-email"],
"rank": 0.61,
"version_cut": null,
"updated_at": "2026-09-28T09:00:00Z"
}
],
"cursor": "…",
"total": 1
}Pass the returned cursor back as since next time to fetch only what's new. An empty items list means nothing has been published for your version yet.
Errors
Error | When | Resolution |
|---|---|---|
| The PAT is malformed, expired or revoked. | Request a new token. |
| The token lacks | Add the scope, or hire and equip the profession first. |
| The craft store is unreachable, or did not answer in time. | Retry with backoff. |
| The membership check could not reach its database. | Retry with backoff. |
POST /api/v1/professions/{profession_code}/craft
Contribute a learning. It is written pending and is never served until review publishes it.
Field | Type | Required | Notes |
|---|---|---|---|
| string | yes |
|
| string | yes | The generalized text, up to 20,000 characters. |
| string | yes | A one-way provenance/dedup hash you compute, such as a sha256 of the body. Never a brand id. It is never returned in a pull. |
| string[] | no | Up to 50 tags, 100 characters each. |
| string | no | A stable slug within the profession, up to 128 characters. Generated if you omit it. |
No other field is accepted.
curl -s -X POST "https://api.opvs.ai/api/v1/professions/email-outreach/craft" \
-H "Authorization: Bearer $OPVS_PAT" \
-H "Content-Type: application/json" \
-d '{
"kind": "learning",
"body": "Founders reply to cold email Tue 07:00–09:00 local far more than any other window.",
"tags": ["timing", "cold-email"],
"source_engagement_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}'
# → 202 {"craft_id": "craft-3f9a1c2b7d10", "consent_status": "pending", "flagged": []}
# → 422 "craft refused: … an email address …" if the body carries one (nothing is stored){ "craft_id": "craft-3f9a1c2b7d10", "consent_status": "pending", "flagged": [] }flagged lists each detail found, as field:kind names and never the text, for example ["body:named_entity", "body:client_quantity"]. The learning was stored, but review must remove each flagged detail before it can be shared; if it cannot, the learning is sealed and never shared. An empty list means nothing was found. Generalize before you send.
Errors
Error | When | Resolution |
|---|---|---|
| The text, a tag or | Remove the detail, or generalize it, and send the learning again. |
| The body, a tag, the tag count or | Shorten it and send it again. |
| A required field is missing, or the body carries a field that is not accepted, such as | Send only the fields in the table above. |
| The | Choose another |
| As for the pull: bad token, missing | See the pull's errors. |
| The craft store or the membership check is unavailable. | Retry with backoff. |
POST /api/v1/professions/{profession_code}/workflows
Contribute a workflow (a SMEAC definition) to the profession's live library. It is written pending until curated.
curl -s -X POST "https://api.opvs.ai/api/v1/professions/email-outreach/workflows" \
-H "Authorization: Bearer $OPVS_PAT" \
-H "Content-Type: application/json" \
-d '{ "workflow_code": "cold-sequence", "version": "1.0.0", "body": { "situation": "…" } }'
# → 202 {"workflow_code": "cold-sequence", "version": "1.0.0", "content_hash": "…", "status": "pending"}
# → 409 if cold-sequence 1.0.0 already exists in this profession{ "workflow_code": "cold-sequence", "version": "1.0.0", "content_hash": "…", "status": "pending" }source is optional: member-contributed (the default) or vendor-seed.
Errors
Error | When | Resolution |
|---|---|---|
| The code, | Replace the detail with a placeholder and send the workflow again. |
| The workflow's strings add up to more than 200,000 characters. | Shorten it. |
| This | Bump |
| Bad token, missing | See the pull's errors. |
| A backing service is unavailable. | Retry with backoff. |
GET /api/v1/professions/{profession_code}/workflows
Pull the published workflow library, with the same since / limit cursor as the craft pull.
curl -s "https://api.opvs.ai/api/v1/professions/email-outreach/workflows?limit=50" \
-H "Authorization: Bearer $OPVS_PAT"
# → 200 {"items": […], "cursor": "…", "total": 1}
# → 403 if your brand holds no active install of email-outreach{
"items": [
{
"id": "…",
"workflow_code": "cold-sequence",
"version": "1.0.0",
"body": { "situation": "…" },
"content_hash": "…",
"source": "member-contributed",
"updated_at": "2026-09-28T09:00:00Z"
}
],
"cursor": "…",
"total": 1
}Errors
Error | When | Resolution |
|---|---|---|
| Bad token, missing | See the pull's errors. |
| A backing service is unavailable. | Retry with backoff. |
GET /api/v1/professions/{profession_code}
A read-only profile of the profession address (member count, freshness). Unlike the craft and workflow routes this is discovery: any authenticated brand can look up a profession, for example before hiring it.
curl -s "https://api.opvs.ai/api/v1/professions/email-outreach" \
-H "Authorization: Bearer $OPVS_PAT"
# → 200 {"profession_code": "email-outreach", "address": "email-outreach@profession.md", …}
# → 404 {"detail": "Profession 'no-such-code' not found"} for an unknown codeErrors
Error | When | Resolution |
|---|---|---|
| The PAT is malformed, expired or revoked. | Request a new token. |
| The token lacks | Add the scope. |
| No profession has this code. | Check the code: it is the part before |
| The address service is unreachable, or did not answer in time. | Retry with backoff. |
CLI & agent tools
The same surface is available from the terminal via the OPVS CLI (opvs profession pull|search|contribute|add-workflow|info) and to agents via the profession marketplace skill (profession_search_craft, profession_pull, profession_contribute, profession_add_workflow).