FEP-7888: Demystifying the context property

Follow-up via #439 - 7888: clarify base case, fix discussion link - fediverse/fep - Codeberg.org to further clarify the “base case” where the context does not resolve to a collection.

At this point I think the only bit I’m unsure of is that in the last PR, I introduced a requirement that says “You MUST NOT assume that an object is included as an item in the collection without proof of its inclusion.” I am wondering if this language should be changed to a SHOULD NOT or to a non-normative “Do not” or “Instead of [assuming]…”

Updated via https://codeberg.org/fediverse/fep/pulls/483 to further clarify that context doesn’t have to be a Collection.

Due to Delivering to Collections can be ambiguous · Issue #486 · w3c/activitypub · GitHub and the desire to be able to make contexts into actors so that they can be followed, we clarify some language in the FEP and rework the examples. There is currently a notion of a “canonical collection” which is not fully developed, and there are several possible approaches to developing it further, but for now I’m leaving it open-ended until some further discussions are had.

Off the top of my head, we could do some combination of the following:

  • define a Context type and some property that directly points to a canonical collection
  • define a property that is @type: @vocab and tells you which property/term to follow as a predicate to discover the canonical collection.
  • let extension types define which property to follow; for example a Conversation extension could define that the property to follow is posts.

I think right now I would say something like:

<Context> a rdf:Class.

<representativeCollection> a rdf:Property.
<representativeCollection> rdfs:domain <Context>.
<representativeCollection> rdfs:range as:Collection.

And then in a separate FEP:

<Conversation> a rdf:Class.

<posts> a rdf:Property.
<posts> rdfs:domain <Conversation>.
<posts> rdfs:range as:Collection.

<Conversation> <representativeCollectionProperty> <posts>.

But I’m not 100% set on this. If it becomes possible to address/deliver a Follow activity to a Collection alone or to some specified hierarchical actor, then there might be less need to do this. It might still end up being worthwhile though, since there is a potential semantic difference after all – a Conversation is perhaps not just a set of posts, and you may want to refer to the conversation separately from referring to the collection.

This change has been made in the above PR.

Per feedback from @devnull I made a few changes in https://codeberg.org/fediverse/fep/pulls/493 to clean up the language and notably move the rational sections to an appendix.

To once again summarize for anyone who wants to know what they would need to do to implement this FEP:

Publishers

Use context for grouping related objects. The grouping should have a purpose, and the objects sharing the same context “belong together” in a way that can’t be said about tag or inReplyTo.

Ideally, make context resolve to something. This will be useful later for backfill, following, synchronization, ownership, moderation, and so on! For now, an attributedTo is probably appropriate.

Consumers

Use context for grouping related objects. The graph source for your objects is up to you, but in the common case where you have a dataset or database of objects, it probably makes sense to have context.id be an index you can select in queries.

Interacting with context

If a context is resolvable and there is a context.attributedTo, you might want to keep them in the loop in the same way that you might consider inReplyTo.attributedTo.

Thank you for graciously considering my feedback.

After re-reading, some additional thoughts:

  1. Move “Publishing context” to the end, before the Appendix mostly because I feel publishing contexts is secondary to consuming/interacting with a context
  2. “Canonical collections of objects within an authoritative context” this section can be excised and moved to the future “Conversational Contexts & Backfill” FEP.
    • For the purposes of the high-level 7888 overview, I posit that it would be sufficient simply to note existing implementations usages of context, and explicitly note an upcoming recommendation later.
  3. “Receiving an interaction with your context” – recommend that this section be excised and moved into a future “Context Ownership” FEP
  4. A lot of the proposed excisions would also mean their related examples in Appendix B would be moved as well.

One more thought – it’s actually a little unfortunate that the FEP has to be written in a formalized FEP-ish style, because your summary in the last post would actually be perfect as the Preamble, but may be considered too prose-y.

My simplification proposal also included this visualization, which is by no means meant to be correct, canonical, or even remotely close to reality.

Since we now have 7888 as the entry point for threaded conversations, and now FEP-efda: Followable objects, I suggest that a visualization and table of child FEPs be added after the Preamble.

Updated via #494 - 7888: Expand preamble into overview - fediverse/fep - Codeberg.org

I reworked the preamble into an overview. It now summarizes the requirements in non-normative prose based on the bit above that you described as “perfect”.

  1. I don’t think it makes sense to talk about publishing after consuming, because people have to publish context before anyone can consume context. Context is fundamentally a sort of authorial intent or purpose, and so consuming context is in some sense reconstructing that purpose, and interacting with context is respecting that intent.
  2. The concept of a canonical collection is a bit hard to split out, since it’s an extension point for further FEPs. I tried to clearly mark it as one and note that concrete implementations of a “canonical context collection” are out-of-scope of 7888. Not sure how much more I can trim out without losing meaning.
  3. “Receiving interactions” is still in there for now, but this one can probably be trimmed down further later. It’s in there right now for conceptual completeness, but there’s an argument to be made that it could be deemed out-of-scope (as distribution to an audience is a separate concern from the grouping of related objects). Perhaps some of this can be moved over to the “sending” side, for example, saying that interactors might want to address their interaction to audience/followers if they want to trigger inbox forwarding.
  4. I don’t know what to do with the examples just yet, but they will probably be up for further review in a later PR.
1 Like

Updated via #495 - 7888: Remove the bit about redistributing received interactions and replace it with client addressing - fediverse/fep - Codeberg.org

For (3) above, “Receiving interactions” has been removed and replaced with “Keeping relevant entities in the loop”. There’s no longer any stuff about redistribution, and the focus is now on the interactor/client considering context owners in the same way that you would consider owners of object, target, inReplyTo, and/or tag (from ActivityPub section 6.1 “Client addressing”).

1 Like

FEP-f228: Backfilling conversations has been submitted. It covers known implementations of a context collection.

1 Like

Would you be open to having this FEP listed as a child/related FEP branching from 7888?

In your diagram above? Sure, I don’t mind.

Hi! sorry i’m very late to this discussion but wanted to contribute my 2 cents.

The AS2 consumer needs to be able to handle any of the following cases:

It’s missing (do nothing)
It’s unresolvable (group by opaque string comparison)
It’s resolvable to something that isn’t a Collection (group by id of that object)
It’s resolvable to a Collection (group by id of that object, and also you can process its items or orderedItems)

This is a good summary but I think it falls short: contexes right now are used for grouping objects in a conversation and it’s very easy to get conflicts.

For example, as of now, mastodon may publish a note #1. It doesn’t use context, sets conversation #abc. pleroma receives that posts and replies #2, processes conversation (because it handles fallbacks) and so #2 has context #abc. misskey may reply #3, but it doesn’t use context at all. pleroma, replying again, will find no context and generate a new one for #4.

Posts #1, #2, #3 and #4 should all be in the same context, as they are “in the same thread”, but because there is no consensus on how this context gets generated, the context field gets inconsistent mid-way and the property itself becomes mostly useless.


I think it’s important to settle for middle ground: having collection contextes would be cool to fetch threads, but it’s ineffective because remote servers need to all be consistent with their context assignation.

I propose a separate approach, and it’s what I’m doing with my software: make context a link to the “first” object. Every reply is “in context of that first note”. This way, in the example from before, pleroma would be able to put the same context in #2 and #4, and potentially even insert a context in #3 from misskey, to be able to grab these notes efficiently from db with just 1 query.

The main value of this proposition is that single softwares can effectively fix contexes from other instances without their contribution, because they know how to fill it. Other proposals require coordination from remote instances to be able to pick a valid context.


Fetching whole conversations is theoretically possible with this model combining the replies collection: upon receiving a note, use its context to go back to the “first note”, and crawl down from there using replies. This is a bit more involved that just having a single paginated collection, but I think the load imposed is comparable since most of the work is fetching the replies themselves rather than the containing collections.

An extension may be introduced to have “thread collections”, and I’d actually be very supportive of that, maybe a thread property? changing context impacts current fediverse software, introducing a new property is opt-in for interested implementations.


Sorry for jumping in so late in the FEP process, hope my 2 cents can be of value, I can say that I’m currently doing this in my software. It’s a bit unfair, as I change remote objects when mirroring them locally, but it’s quite reliable in stitching up threads and allows me to fetch a bunch of replies very quickly!! (:

1 Like

Hi @alemi, timely reply!

I just published a “state of the union”-style summary of what’s been going on around context

(Although since I’m posting on SocialHub, perhaps I should post the SH link instead: The state of conversational contexts (February 2025))


There will likely always be implementors who use context via opaque string comparison. We should allow that usage due to prior art.

With regard to an inconsistent context, my opinion is that if your software supports resolvable contexts, you should attempt to inherit the resolvable context closest to root level. Otherwise it is perfectly ok for you to generate your own context or not use one at all (again, prior art.)

context being a link to the first note makes sense, that could be a valid use case for context as well. The ForumWG has no interest in forcing only one usage of context (as @eprodrom noted many times, doing so would violate the original intent of the ActivityStreams context property.)

Traversing the replies collection is lossy, if you encounter a dead node, you lose everything below it. Likewise if you traverse up inReplyTo and encounter a dead node, you lose everything above. So there are reliability concerns. I have no specific opinion on its scalability yet, although I know Mastodon is interested and looking at a PR implementing this.

1 Like

This will generally happen when interacting with context-unaware softwares, and there’s nothing that can be done to avoid this. Instead, you have some strategies available to you:

  • maintain a list of aliases or equivalences for context ids. so you know that when you see tag:mastodon.example,2025-02-21:objectId=924340550:objectType=Conversation on one object, that it is equivalent to https://pleroma.example/contexts/86238219-b7ba-47a2-acd2-6c14d9e96d66 or that both of these are equivalent to https://nodebb.example/topic/18647 and so on. the exact nature of this equivalence is a bit open-ended; you could treat them as different identifiers for the same object, or you could treat one identifier as canonical, or you can treat each identifier as a syndicated copy.
  • when you encounter an object without a context, you can traverse whichever links you find relevant (such as inReplyTo or replies) and attach the object to the nearest context. however, note that the object might intentionally be published without a context; there is no way to detect whether the omission of context is intentional or not. it’s not automatically a good idea to assume that a contextless object belongs in a reply tree. consider an Article that is inReplyTo a different Article, but the two Articles might be considered to have separate contexts and be discussing different things. the use of inReplyTo denotes only that the second article is a response to the first article.

in general, it bears repeating: be careful when making assumptions.

thread was proposed in a different FEP: fep/fep/76ea/fep-76ea.md at main - fediverse/fep - Codeberg.org
There are no implementations and I don’t like the reverse-chronological order requirement, but I think thread is better than context.

Updated via https://codeberg.org/fediverse/fep/pulls/523

  • the rdfs:label of as:context is roughly “was created in relation to”, citing James Snell in a github issue explaining the intended usage of the context property.
  • many applied usages of the concept of a “context” include behavior where deleting a context deletes or garbage-collects anything within that context. this is not a requirement or recommendation, but it is called out as possible behavior.
  • exactly how to participate in a context or copy an existing context is protocol-dependent and left out-of-scope of this FEP; to be followed up on in future FEP efforts
  • examples are simplified to leave out protocol details and focus on publishing and consuming context. a new example 4 is added for demonstrating the extension point for “canonical collections”.

I think that FEP-7888 is getting close to stable, with excised sections being able to use of the extension points left within 7888. For example:

  • a FEP for “canonical context collections” can make use of the “canonical collection” extension point by specifying that if context resolves directly to a Collection, then that Collection is itself the “canonical collection”.
  • a FEP for a Conversation type and a posts property can also make use of the “canonical collection” extension point by specifying that Conversation.posts is such a canonical collection.
  • a FEP for some kind of Participation activity (for lack of a better name) can define a protocol where that activity’s side effects are intended to request inclusion or acknowledgement into the canonical collection (in the same way that FollowAccept Follow results in manipulating the followers collection, or Like for likes, or Announce for shares, or a hypothetical Reply for replies, or a QuoteAccept Quote flow, or so on)

One option that remains open is to use outbox as a reverse-chron list of activities for backfilling. In the hypothetical case of a Conversation, its posts could be a Collection of what objects are included in there, and its outbox could contain the activities – exact protocol left open-ended, but you could imagine either listing the activities directly (probably combined with inbox forwarding), or otherwise using 1b12-like Announce-wrapping usage to “share” activities indirectly if that’s desired, or otherwise Announcing contentful objects directly to “share” them into the conversation… that’s out-of-scope, though, and should be discussed in those extension FEPs if/when they are submitted.

cc @devnull (i can’t mention @julian@community.nodebb.org from here) and @angus (and i believe some other people were interested but i am having trouble recalling who exactly they all are rn)

I know this FEP is a description of possible use cases and related best practices, so I’ll try not to debate it too much, but I have a few concerns.

I think this is misleading. The non-normative “was created in relation to” context description was referring to a specific example being discussed in the GitHub thread. Earlier in that thread, Snell stated that context was more generally “a larger context within which the [object] exists” (circular, but both comments are were informal replies to clarify the difference between scope and context). And elsewhere, Snell says (again, informally) that context “is really intended to allow objects and activities to be logically grouped”. In that sense, audience and tag are not only explicit indicators of context (versus being described as “implicit” in the FEP), they could be viewed as being more explicit forms of context than context (which is more vague). At least, for tag, that’s arguably true. Of course, one could claim the meaning of audience is also very ill-defined.

As the FEP mentions, the AS2 normative description describes context as being “intentionally vague”. The normative definition is also circular: “grouping objects and activities that share a common originating context or purpose”.

In any case, I think the FEP represents reasonable suggestions about specific ways to use context. I do hope it’s not used in the future to pressure developers to not use context in other creative and spec-conformant ways.

For example, other uses of `context:

  • may not embody or represent shared purpose
  • may not serve as a kind of container that objects exist “within”
  • might have multiple contexts (it’s not a functional property)
  • may not represent a set of objects intended to be viewed or processed together

There are potential use cases where some of all of those statements are true. They are not FEP-7888 use cases, but they are valid AS2 context use cases.

1 Like

thanks, Steve. i don’t want to be misleading and i don’t want to enforce a singular narrow/limited use of context, but i do want to focus more on that “logically grouping” use case as “the intended usage”. definitionally, i want to emphasize reason/purpose as a relation where the current object exists “within” or "was created in relation to” some larger entity, as i believe the example presented in that github issue is the most straightforward explanation to date, outside of this fep (which i want to refine and polish as much as possible).

maybe explicit vs implicit is not the best wording, but what i meant by it was that no one can ever “own” a hashtag, or a chain of replies, or a set of recipients, or so on. you can query for the presence of explicit properties and values, but that is not an “explicit context”. perhaps i should use the word “reified”, but i wonder if the word “reified” is broadly understood, especially here.

in any case the “7888 use cases” allow for the bullet points you listed, but they do dilute the semantics as to revert the term to being functionally useless again (except for the multiple contexts bit, which has an associated example). behaviorally, i didn’t want to enforce this, but the bit about deleting or garbage-collecting objects without a purpose ties more closely into protocols of e.g. social networks or the fediverse, where these behaviors are implicit and the implications are somewhat loose, such as the notion of a “post” not being fully defined either. but insofar as your worldview deals with “posts”, the context of a post is likely a conversation, and honestly such protocols might as well create limited profiles of AS2.

1 Like

I’m hoping the revised 7888 is at least a little more accessible for those wishing to implement a federated threaded discussion model.

One thing I want to point out is that the current implementations set as:context, the context resolves, but resolves to an OrderedCollection.

Are we considering that this is no longer an accepted implementation of 7888, or can this still be accepted, as backfill is already working in-practice between a number of implementors, just not formalized in an FEP (we should probably write one…) I think 7888 is carefully written so as to not explicitly define the type, but I’m trying to think ahead (as @thisismissem warned us to, today)

1 Like

See fep/fep/2931/fep-2931.md at main - fediverse/fep - Codeberg.org and its discussion thread FEP-2931: Representing context with a Collection for this usage.

I think 7888 is more general than just “backfill” and therefore it straddles a line between “informational” and “implementation”. Right now, 7888 is a bundle of recommendations:

  • SHOULD have purpose
  • SHOULD resolve
  • SHOULD have an associated Collection of things included in a context (as acknowledged by a moderator), which MAY be signaled by context.type
    • SHOULD NOT assume an object is included in such a Collection just because it declares context / SHOULD make effort to verify inclusion / SHOULD treat claims as unverified by default
  • SHOULD consume objects sharing the same context in the same processing context
  • MAY set same / different / no context when interacting with an object that has context
    • SHOULD notify context.attributedTo and maybe context.followers

I want to caution against the view that context MUST be a Collection, since this is too restrictive. It would be like saying audience or to or cc must be a single Collection. Rather, one should think of context as an object that provides a reason or purpose for existing to the current object. In a lot of cases today, that purpose is threading (insofar as the thing you’re looking at is a “post”, it might exist in a “conversation”). Think of it as a way to construct a bag of things that belong together.