Skip to content

Researcher Profile Specification

The Researcher Profile specification defines two things:

  1. A schema defining what a Researcher Profile is. The profile.jsonld document extends schema:Person, adding researcher-specific fields (expertise, provenance, career stage, paper statistics) to the standard Person schema, plus a manifest that lists all associated files.

  2. A file structure for deeper profile data: content too large, or the wrong shape, to embed in JSON, such as Markdown prose (expertise, summaries), JSON collections (papers, grants), and binary data (embeddings).

The document references these files via its manifest (hasPart and subjectOf arrays). Together they form the profile.

This document contains the core metadata about the researcher, and it also serves as the manifest, with a list of pointers to external information that did not fit inside this core JSON document.

{
"@context": "https://profiles.databio.org/context/v1.jsonld",
"@id": "https://orcid.org/0000-0002-1825-0097",
"@type": "Person",
"conformsTo": "https://profiles.databio.org/context/v1.jsonld",
"name": "Ada Lovelace",
"rid": "0000-0002-1825-0097",
"provenance": "third_party",
"license": "https://creativecommons.org/licenses/by/4.0/",
"level": "full",
"affiliation": "Analytical Society",
"field": "Mathematics",
"summary": "Mathematician who wrote the first published algorithm intended for a machine.",
"expertise": [
"symbolic-computation",
"exposition-of-machinery"
],
"paper_stats": {
"corresponding": 2,
"first": 2,
"last": 0,
"middle": 0,
"total": 2,
"unknown": 0,
"year_max": 1843,
"year_min": 1843
},
"hasPart": [
{
"@type": "Collection",
"name": "Works",
"visibility": "public",
"role": "works",
"encodingFormat": "application/ld+json",
"contentUrl": "sources/papers.jsonld"
},
{
"@type": "DigitalDocument",
"name": "Summary: lovelace1843notes",
"visibility": "public",
"role": "paper_summary",
"paperId": "lovelace1843notes",
"encodingFormat": "text/markdown",
"contentUrl": "sources/summaries/lovelace1843notes.summary.md"
}
],
"subjectOf": [
{
"@type": "DigitalDocument",
"name": "Expertise",
"visibility": "public",
"role": "expertise",
"encodingFormat": "text/markdown",
"contentUrl": "personality/expertise.md"
}
]
}

Additional profile documents (the backing files)

Section titled “Additional profile documents (the backing files)”
lovelace/
profile.jsonld
personality/
expertise.md
SOUL.md
sources/
papers.jsonld
summaries/
lovelace1843.summary.md
...
...

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” are interpreted as described in RFC 2119/8174 when in ALL CAPITALS.

TermDefinition
Researcher Profile (RP)A directory of files conforming to this specification describing one researcher.
ProfileConvenience alias for Researcher Profile when used in this context.
Base URL (<base>)The URL prefix under which a profile’s files are served.
ArtifactAny file the profile enumerates in its manifest.
PublisherThe entity serving the profile at Base URL <base>.
SubjectThe researcher the profile describes. Exactly one per profile.
ConsumerSoftware that reads a published profile.

The profile.jsonld file is a JSON-LD document that extends schema:Person with researcher-specific fields. It serves two roles. It is structured metadata about the researcher, and it is the external file manifest: the schema:hasPart and schema:subjectOf arrays list every external file attached to this profile.

Three fields are REQUIRED for validation: a document missing any of them fails to load. Five more are required on the wire; every conforming published document carries them, but the reference implementation fills them in when absent, so an authoring tool may omit them and still produce a conformant document once loaded and re-saved.

FieldRequiredDescription
nameREQUIREDNon-empty display name
ridREQUIREDCanonical ORCID or local:<slug>-<hex6>
provenanceREQUIREDorcid_verified, self_published, third_party, synthetic, or historical
provenanceNoteoptionalOne human sentence saying how the document was produced when provenance alone does not say (e.g. “self-reported via a structured interview on 2026-09-12; unverified”). Consumers SHOULD display it next to the summary
@contextrequired on the wire, defaulted on load"https://profiles.databio.org/context/v1.jsonld" (exact string); absent is filled in with this value
@typerequired on the wire, defaulted on load"Person"; absent is filled in
conformsTorequired on the wire, defaulted on loadEquals the @context IRI; a present but wrong value fails to load, an absent value is filled in
@idrequired on the wire, defaulted on loadORCID IRI, profile URL, or #me; absent is filled in with url if set, else #me
levelrequired on the wire, defaulted on loadlite, full, or deep (see below); absent is filled in as full
licenseRECOMMENDEDSPDX IRI or license URL
dateModifiedRECOMMENDEDISO 8601 timestamp
visibilityoptionalpublic, limited, or private (default: public)
expertiseoptionalArray of topic labels
interestsoptionalInterest labels. When rp:researchInterests is present, rebuilt from it: the entries with a positive weight (see Research interests)
not_interestsoptionalAuthoritative non-interests. When rp:researchInterests is present, rebuilt from it: the entries with a negative weight
rp:researchInterestsoptionalTyped, weighted interests; the canonical form of the two lists above (see Research interests)
career_stageoptionalDate-anchored eligibility facts (see below)
collaboratorsoptionalDeclared connections to other researchers (see below)
researchOutputsoptionalResearch outputs other than papers: grants, software, datasets, protocols, etc. (see below)

The level field describes how much content a profile contains:

LevelDescription
litePublic bibliometric identity: metadata + works list. No summaries, no persona.
fullComplete persona: paper summaries, expertise.md, SOUL.md, full embedding index.
deepEverything in full plus grants, CV, and web sources.

The career_stage field is an object (not a simple value) that records facts for grant eligibility evaluation:

FieldRequiredDescription
as_ofREQUIREDISO date when facts were assessed
terminal_degree_yearoptionalInteger or null
first_r01_equivalent_yearoptionalFirst R01/DP1/DP2/etc.
current_rankoptionalCurrent rank or position: assistant_professor, associate_professor, professor, research_faculty, staff_scientist, postdoc, graduate_student, undergraduate, clinician, industry, other; null when unknown
tenure_statusREQUIREDEnum value
independenceREQUIREDEnum value
evidenceREQUIREDCitation of sources
confidenceREQUIREDhigh, medium, or low
sourceoptionalWho asserted the stage: self_reported (the profile owner said so) or inferred (default; a builder guessed from evidence)

A self-reported stage outranks an inferred one. A builder, a merge or any other writer that produces an inferred stage MUST NOT replace a stored self-reported stage; it MAY fill only the facts the self-reported stage leaves null (the terminal-degree year and type together, never one without the other). Builders never write self_reported.

The collaborators field records the researcher’s declared connections. It is mapped to schema:knows in the JSON-LD context.

Each entry is one of:

  • A string: a name alone ("Alice Smith")
  • An object with structured details:
FieldRequiredDescription
nameREQUIREDDisplay name
affiliationoptionalInstitutional affiliation
relationshipoptionalHow they are connected (see recommended values below)
urloptionalThe collaborator’s profile base URL (enables network traversal)

The relationship field is a free string: publishers MAY use any descriptive value. No formal ontology for researcher-to-researcher relationship types exists; in its absence, publishers SHOULD use one of these RECOMMENDED values, listed from strongest to weakest:

PriorityValueMeaning
1advisorServed as this researcher’s advisor (doctoral, postdoctoral)
2adviseeWas advised by this researcher
3coauthorHas co-authored papers with this researcher
4colleagueWorks at the same institution or in the same group
5collaboratorGeneral research collaboration

Each collaborator entry carries a single relationship value. When multiple relationships apply (e.g. an advisor who is also a coauthor), publishers SHOULD use the strongest one (the highest in the priority list). Weaker relationships like co-authorship are already discoverable from the paper record, so declaring the relationship that is not in the bibliography adds more information.

Consumers MUST handle unknown relationship values gracefully.

The url field, when present, points to a hosted researcher profile. Because the JSON-LD context defines url as schema:url with @type: @id, a JSON-LD processor treats it as an IRI, linking this person node to the collaborator’s profile. Plain JSON consumers see it as an ordinary URL string.

Connections are unidirectional: if profile A lists B, B does not automatically list A. Each profile declares its own connections independently.

Examples:

Name-only:

"collaborators": ["Alice Smith", "Bob Jones"]

Structured with profile link:

"collaborators": [
{
"name": "Alice Smith",
"affiliation": "Example University",
"relationship": "coauthor",
"url": "https://profiles.example.org/p/alice-smith"
}
]

Using @id to make the collaborator entry itself a linked-data node (pointing at the collaborator’s profile):

"collaborators": [
{
"@id": "https://profiles.example.org/p/alice-smith",
"@type": "Person",
"name": "Alice Smith",
"affiliation": "Example University",
"relationship": "coauthor"
}
]

In this form a JSON-LD processor resolves the @id as the collaborator’s identity IRI. This is the strongest form of linking: it asserts that the collaborator is the person described at that URL, rather than only that a URL exists for them.

The researchOutputs field records non-paper outputs the subject produced: software, datasets, standards, and anything else that is a research product but not a publication. Papers are not listed here; they live in sources/papers.jsonld. This array is about what the researcher made, not about the files in the profile directory (those are the manifest, below).

Each entry is a research output, the format’s base type for everything a researcher produces. Every research output carries the same core:

FieldRequiredDescription
typeREQUIREDFree-form token naming the kind of output, e.g. software, dataset, standard
nameREQUIREDDisplay name of the output
descriptionoptionalOne or two sentences on what it is
urloptionalWhere the output lives
@idoptionalIdentity IRI for the output: a DOI, a repository URL, a grant IRI
@typeoptionalJSON-LD node type, when the output has a meaningful one

Recommended type vocabulary. The following tokens are RECOMMENDED so that consumers can group outputs consistently:

software, dataset, protocol, reagent, model, grant, abstract, presentation, patent, standard.

This is a recommended list, not a closed enum. The type vocabulary is open: publishers MAY use other values, and consumers MUST handle unknown values gracefully rather than rejecting the entry.

Specializations. A research output type MAY specialize the base by adding its own fields while keeping the core above. A paper record in sources/papers.jsonld is exactly such a specialization: it is a research output whose name is the work’s title and whose @type is ScholarlyArticle, plus the bibliographic, authorship and access fields a scholarly work needs. Future output kinds — grants, presentations, patents and the rest of the recommended vocabulary — are expected to specialize the base the same way, each adding the fields its kind requires. A consumer that understands only the core fields can therefore read every research output, whatever its kind.

Example:

"researchOutputs": [
{
"name": "KinTool",
"type": "software",
"url": "https://kintool.example.org"
}
]

The hasPart and subjectOf arrays form the external file manifest, a list of every file attached to the profile:

  • subjectOf: persona documents (expertise, SOUL)
  • hasPart: everything else (works, grants, summaries, embeddings)

Each entry is an ArtifactRef:

FieldRequiredDescription
contentUrlREQUIREDRelative path from profile base
@typeoptionalDefaults to DigitalDocument
nameoptionalHuman-readable label
roleoptionalMachine token (see vocabulary below)
encodingFormatoptionalMIME type
paperIdoptionalLinks summary/fulltext to its paper
visibilityoptionalArtifact privacy tier (see Privacy)
derivedFromoptionalRoles or paper ids this artifact was derived from; its effective tier is the most restrictive of its own and its sources’
bytesoptionalSize for fetch budgeting
sha256optionalIntegrity check

Publishers SHOULD set name, role, and encodingFormat on every entry; a consumer can only find an artifact by role when it is present.

A consumer MUST NOT construct artifact URLs by convention. Find the entry by role (or paperId) and read its contentUrl.

TokenArrayArtifact
expertisesubjectOfpersonality/expertise.md
soulsubjectOfpersonality/SOUL.md
topicssubjectOfpersonality/topics.json
workshasPartsources/papers.jsonld
grantshasPartsources/grants.jsonld
seed_papershasPartsources/seed_papers.jsonld (tier private by default)
citationshasPartsources/citations.json
paper_summaryhasPartsources/summaries/<paper_id>.summary.md
paper_fulltexthasPartsources/papers/<paper_id>.md
cvhasPartsources/cv.md
interviewhasPartsources/interview.md (tier private)
webhasPartsources/web/<n>-<host>.md
embedding_indexhasPartembeddings/index.json
embedding_index_sqlitehasPart.cache/embeddings.sqlite (tier private)
agent_entry_pointhasPartSKILL.md
htmlhasPartindex.html

Consumers MUST ignore unknown role values.

provenance is a headline label for trust level:

ValueMeaning
orcid_verifiedORCID record links back to this profile
self_publishedPublished by the subject, no ORCID verification
third_partyPublished by someone other than the subject
syntheticNot a natural person (AI agent, test fixture)
historicalReal person who cannot hold an ORCID

A profile built from a structured interview with the subject (no or few publications) uses self_published and carries a provenanceNote saying so; nothing in such a profile has been checked against publications or records.

The optional proof array carries fine-grained verification:

Proof kindWhat it proves
orcid_roundtripORCID record points back (the self-hosted option)
domain_wellknownControl of domain via .well-known challenge
key_signatureDetached JWS over canonicalized document
orcid_login (registry-issued)The registry serving this document saw the profile’s owner sign in with ORCID iD orcid

Consumers MUST ignore unknown proof kinds.

A registry that hosts profiles and signs people in with ORCID can vouch for that sign-in itself. It does so with an orcid_login proof:

MemberValue
kind"orcid_login"
issuerThe base URL of the registry serving the document
orcidThe bare ORCID iD (0000-0002-1825-0097), equal to the ORCID in rid
verifiedAtWhen the registry last confirmed the ORCID sign-in (ISO 8601)

A registry computes this proof each time it serves the document. It MUST NOT store it, and it MUST drop any copy a document author supplies. A document carries at most one, and its orcid MUST equal the ORCID in rid.

A consumer MUST treat an orcid_login proof as valid only when it fetched the document from the issuer origin (or re-fetches it from there to check). A copy served by any other host proves nothing: anyone can paste the JSON into their own document.

Self-hosted profiles have no registry to vouch for them. They use orcid_roundtrip instead: the ORCID record’s website list points back to the profile.

Two vocabularies carry the data:

PrefixIRIPurpose
schema:https://schema.org/Person, works, grants, identifiers
rp:https://profiles.databio.org/context/v1.jsonld#Profile-specific terms

The context also maps conformsTo to dcterms:conformsTo and declares the xsd prefix for typed literals such as datePublished.

Consumers can read profiles as plain JSON without dereferencing the context.

These files hold data that is too large, or the wrong shape, to embed in JSON.

<slug>/
profile.jsonld # REQUIRED. The record and manifest
index.html # landing page (written by `rp render`)
SKILL.md # agent instructions (optional)
personality/
expertise.md # full/deep profiles
SOUL.md # full/deep profiles
topics.json # LLM-labeled research topics (optional)
sources/
papers.jsonld # REQUIRED. Works collection
grants.jsonld # when grant records exist
seed_papers.jsonld # interest seed papers (optional). PRIVATE by default
citations.json # citation graph (optional)
summaries/<paper_id>.summary.md
papers/<paper_id>.md # full text. PRIVATE by default
cv.md # deep profiles
web/<n>-<host>.md # deep profiles
embeddings/
index.json # Searchable profiles
<backend>.bin
<backend>.chunks.json
.cache/
embeddings.sqlite # derived local index. PRIVATE
.keys/ # signing keys. Never served

Build state lives in .build/<slug>/, outside the profile directory.

  • <base>/profile.jsonld MUST resolve: it is the single discovery endpoint.
  • All served paths carry an explicit extension (.jsonld, .json, .md, etc.).
  • There is no content negotiation, so the same layout works on every static host.
  • paper_id is chosen by the producer and is opaque to consumers. It names files (sources/summaries/<paper_id>.summary.md) and fragments (#paper/<paper_id>), so it SHOULD contain no path separators or whitespace. The reference validator does not check its characters.

sources/papers.jsonld is a Collection whose hasPart contains ScholarlyArticle nodes. Reached via the works manifest entry, not by path.

FieldRequiredDescription
@typeREQUIREDScholarlyArticle
@idREQUIREDDOI IRI > OpenAlex IRI > #paper/<paper_id>
nameREQUIREDPaper title
paper_idRECOMMENDEDInternal ID; joins to summaries
datePublishedoptionalYear as string
authorRECOMMENDEDPerson nodes ({"@type": "Person", "name": ...}), one per author, in order

Build fields (status, contaminated) stay in .build/, never here.

sources/grants.jsonld holds MonetaryGrant nodes when present.

FieldDescription
@typeMonetaryGrant
@id#grant/<grant_id>
nameGrant title
identifierAward number
rolepi, co_pi, co_i, other
statusfunded, pending, completed

sources/seed_papers.jsonld is an optional Collection of papers that define the person’s research interests: papers they admire, build on, or want to work near. It asserts interest, never authorship. It is reached via the seed_papers manifest entry, and its default tier is private; the owner may re-tier it.

Each hasPart entry is a ScholarlyArticle node carrying only lightweight metadata:

FieldRequiredDescription
@typeREQUIREDScholarlyArticle
@idREQUIREDOpenAlex IRI > DOI IRI
nameREQUIREDPaper title
openalex_id / doione REQUIREDBare OpenAlex work id (W…) or bare DOI
datePublishedoptionalYear as string
isPartOfoptionalPeriodical node, for display
abstractoptionalAt most 8000 characters; the embedding input
topicsoptionalOpenAlex topic ids (T…)
dateCreatedoptionalWhen the seed was added
added_viaoptionalowner, interview, feed_upvote or migration

Seeds carry no authors, full text, summary or citation counts. Consumers MUST NOT list seed papers as the person’s works, count them as publications, or feed them into a synthesized narrative of the person’s own work. A consumer MAY use them as an interest signal (ranking, matching, recommendation). Seed chunks in a published embedding index (source_type seed_abstract) take the tier of the seed list and MUST NOT be shown as the person’s own text.

A file whose manifest role is paper_fulltext or paper_summary is a text artifact. It MUST be readable text, not binary data decoded as text. The rule is “no garbage”, not “ASCII only”: Greek letters, math symbols, accented names, curly quotes, and dashes are all fine. A text artifact fails when any of these holds:

  1. Its bytes are not valid UTF-8.
  2. It contains a NUL character (U+0000).
  3. U+FFFD REPLACEMENT CHARACTER makes up more than 1% of its characters.
  4. Control characters other than tab (U+0009), line feed (U+000A), and carriage return (U+000D) make up more than 2% of its characters. A control character is one in U+0000-U+001F or U+007F-U+009F (Unicode general category Cc).
  5. It is a raw PDF body: after an optional byte order mark and whitespace it starts with %PDF- followed by a digit, or it contains two or more distinct PDF structure markers from this list: a line starting with <n> <n> obj, a line starting with endobj, a line starting with endstream, stream followed by a line break and then x or U+FFFD, a line starting with startxref, a line starting with %%EOF. One marker alone never fails, so prose that mentions endobj is safe.

Shares count Unicode code points over the whole decoded text. For text that is not valid UTF-8, a validator decodes it with each invalid sequence replaced by U+FFFD and applies rules 2-5 to the result as well. The thresholds are shares, not “any”, because real PDF text extraction leaves a few stray characters behind (a form feed per page break, math-font brackets mapped to control codes, an unmappable glyph as U+FFFD), while binary decoded as text is dense with them.

Two conformance levels are defined.

A profile conforms at Base level when:

  1. <base>/profile.jsonld resolves via HTTP GET
  2. The document validates against schemas/profile_jsonld.schema.json
  3. @context references a known researcher-profile context version
  4. conformsTo contains the @context value
  5. name, rid, and level are present and well-formed
  6. Every hasPart / subjectOf entry resolves at its contentUrl
  7. Every paper_fulltext and paper_summary file it serves passes the text artifact rule

Meets all Base requirements plus:

  1. <base>/embeddings/index.json resolves and is well-formed
  2. The embedding blob contains exactly count * dim float32 values
  3. backend_spec names a baseline model (all-MiniLM-L6-v2, dim 384)
  4. Chunk metadata file resolves with count entries

See Embeddings for the full embedding format.

Conformance is established by validation, not by declaration. The manifest reveals whether artifacts exist, but a consumer MUST validate rather than trust.

  • RO-Crate packaging: compatible with future wrapping but not required.
  • Central discovery hub: this specification defines no central registry or federation protocol. A registry is any host that serves the API, static or dynamic, and each one publishes its own collection.jsonld listing.
  • Chatbot interface: persona methods are SDK features, not format.
  • SPARQL: JSON-LD is for crawlers and agents, not triplestores.
  • Profile creation: how to build is out of scope.
  • DIDs/Verifiable Credentials: identity uses a simpler proof envelope.
  • Accounts and identity providers: how a server authenticates a person (institutional SSO, ORCID, e-mail) is out of scope, and so is how a server mints and manages keys. Command-line login specifies only how a command line obtains a credential.

rp:researchInterests is a list of ResearchInterest entries. Each one links the person to one concept with an optional signed weight. It follows the Weighted Interest Ontology pattern (person, wi:WeightedInterest, topic, with wi:weight); rp:ResearchInterest is declared a subclass of wi:WeightedInterest. That ontology is a precedent, not a standard, and it has no fixed range or neutral value, so this spec adds both.

FieldRequiredMeaning
conceptREQUIREDThe term (below)
weightoptionalA number from -1 to 1. +1 is a core interest, 0 is declared neutral, -1 is a hard exclude, and values between -1 and 0 mean rank lower. A missing weight means unknown, never 0.
methodREQUIREDdeclared (the person said it), inferred (computed from papers or written by a model), or imported (copied from another record, e.g. ORCID keywords)
generatorREQUIREDWhat produced the entry, e.g. user, llm, profile-wizard, openalex-topics@2026-09
assertedAtREQUIREDWhen the entry was made (prov:generatedAtTime). The same person may reassess a concept; this says which entry is newer
evidenceoptional{papers: [...], share: 0.45}. Raw counts and shares live here, never in weight

A concept has one of two forms, never a mix:

  • Coded: @id (the term’s own IRI), system (the vocabulary URI, skos:inScheme), code (skos:notation), display (the label snapshot, skos:prefLabel), and an optional version (the release of the pinned vocabulary copy). The field names follow FHIR Coding.
  • Text-only: label plus unmapped: true, with no @id, system or code. The fallback when no vocabulary term fits.

Vocabularies says which vocabularies to use and what system and version hold for each.

Precedence. Several entries may cover the same concept (same system and code, or the same text-only label ignoring case). Exactly one counts: a declared entry beats an inferred or imported one, and among equals the newest assertedAt wins.

Projection. When rp:researchInterests is present, interests and not_interests are rebuilt from the entries that count: a positive weight is an interest, a negative weight a non-interest, and an entry with no weight or weight 0 is in neither list. A free-text list written by a tool or a person becomes text-only entries (+0.5 for an interest, -0.5 for a non-interest).

The spec says what a weight means, not how to compute one. An entry inferred from paper counts (evidence.share) leaves weight unset: how often a topic appears in someone’s papers is not how much they care about it.

An export MAY give a FOAF view with foaf:topic_interest for concepts with a positive weight only. Interests are never exported as schema:knowsAbout, which states expertise, not interest.

rp:sectionVisibility declares privacy for the finite inline sections summary, expertise, focus, methods, SOUL, clinical, site capabilities, regulatory experience, contact, and background. A section is never less restrictive than the whole profile. Optional clinical profiles may add rp:therapeuticAreas, rp:siteCapabilities, rp:regulatoryExperience, a trials collection at sources/trials.jsonld, and clinical_expertise Markdown. Trial entries use a validated NCT identifier and describe only confirmed researcher relationships; an unknown role remains absent.

Both clinical files are ordinary manifest entries and are optional everywhere:

PathSlotroleDefault tier
sources/trials.jsonldhasParttrialslimited
personality/clinical_expertise.mdsubjectOfclinical_expertisepublic

Trials default to limited because trial participation is site and patient-adjacent operational detail; the narrative describing it is authored for publication and stays public. Trial statistics are derived from the records present, never authored: a count that can disagree with the collection under it is a count nobody can trust, and an unknown enrollment stays unknown rather than becoming zero.

A profile carrying trials and no papers is complete. An empty sources/papers.jsonld, or none at all, is the normal shape for a clinical or non-publishing researcher, and no consumer may treat it as a broken profile.

These extensions add no terms of their own to the @context. Every new key is a compact IRI under the already-defined rp prefix, which JSON-LD expands through that prefix rather than through @vocab. The one exception is rp:researchInterests: its SKOS, wi: and PROV mappings need a scoped context, which the @context defines. No existing term changes meaning.