Interoperable Serendipity

A while ago, I wrote about something I call Interoperable Serendipity (If you prefer to watch videos, I also gave a 20min talk).

TLDR, Interoperable Serendipity happens when apps built by different developers work together without explicit coordination. For example, imagine I build a Task Manager, and you also build one without knowing that mine exists. I would say we have achieved Interoperable Serendipity if both apps work with each other’s data out of the box.

My original idea was for the Solid Protocol, but it totally applies to ATProto as well. Since permissioned data is in the works, I’ve started paying more attention to ATProto and I wanted to explore this here as well. Fortunately, this also applies to public data so we can talk about it right now!

Are Lexicons interoperable?

In the ATProto world, we’re using Lexicons to shape our data. Looking at the official docs, Lexicons are intended to provide Interoperability. However, I’ve noticed that in practice most people are creating app-specific Lexicons. In my opinion, this goes against interoperability because the point of having interoperable data is that it’s decoupled from applications.

In Solid, we use RDF (and yes, I’m aware why ATProto isn’t using it… although I don’t agree with the arguments). Regardless whether you like RDF or not, a huge advantage is that there are already many vocabularies in use, like schema.org which you may be familiar with.

So if I am to build, for example, a Recipes Manager, it’s very likely that I choose schema.org/Recipe to model my data. And it’s a lot more likely that two apps built by different developers are interoperable out of the box.

Now, recently I was happy to see that this trend of using app-specific Lexicons seems to be changing with the introduction of standard.site. Unfortunately, looking under the hood it’s not working quite as I thought.

Example: Long-form publishing with standard.site

On the surface, it seems like the standard.site Lexicon solves exactly the problem I’m talking about. It provides a shared vocabulary to use when publishing long form content, and apparently it’s already supported in multiple applications (like Leaflet and Offprint). There’s even aggregated sites like Standard Reader where you can find publications from different sources.

However, after I started exploring the data itself, I saw a different story. Let’s look at two publications from the official blogs:

Indeed, they are both standard.site.document records. But if you look at the content, each has their own format (pub.leaflet.content and app.offprint.content respectively).

So I have to assume that the Standard Reader team is aware of this, and they have implemented parsers and renderers for both custom contents. Looking at the source code, this confirms my suspicions as they have a dedicated folder for each 3rd party platform (also one for Pckt).

This is what I call “Intentional Interoperability” in my taxonomy. Basically, anyone who wants to be interoperable with any of these platforms, has to do it intentionally. In this situation, the chances of achieving Interoperable Serendipity are very slim.

But the problem goes beyond the current situation. Imagine I want to build yet another Blogging app. Since standard.site exists, it was my assumption that I would be able to use that Lexicon and the data generated with my app would be instantly interoperable with the whole ATProto ecosystem. But the truth is that it won’t happen. Instead, I have two choices:

  1. Adopt a 3rd party Lexicon that is coupled to an application (Like pub.leaflet.content or app.offprint.content). This is not ideal for multiple reasons, but most of all because I don’t think that’s the intended use of those Lexicons.
  2. Create my own Lexicon, and pray that it gets popular enough for the entire ATProto ecosystem to support it as well.

(Yes, I’m aware that standard.site.document records have a textContent field, but that’s explicitly documented as a plaintext representation that cannot contain rich text… So it’s not really a solution)

The road ahead

So, what do you guys think? Is this idea something you would like to see in the ATProto ecosystem? If so, how can we get there?

In my blog post / talk, I discuss some ideas to move up from the lower levels of my taxonomy towards Interoperable Serendipity. For ATProto in particular:

  • It would be nice to change the mindset from “app Lexicons” to “data Lexicons”. It’s fine for people to create a new Lexicon if they can’t find an adequate one for their app, but it would be better to define those as reusable out of the box, rather than coupling them to apps. For example, I’ve had to create a couple of custom vocabs for my own Solid apps, but I’ve been publishing them under vocab.noeldemartin.com rather than coupled to app domains.
  • Improve Lexicon discovery. I’m aware of the Lexicons browser, but it’s very difficult to find appropriate Lexicons and as I mentioned it doesn’t seem like most of them are intended to be reusable.
  • Is there a Lexicon extension mechanism? In RDF, it’s very common to find a vocabulary that is almost what you need, but doesn’t quite cover all your requirements. In those cases, developers don’t have to create a vocab from scratch. Instead, they can extend it with extra functionality whilst the basic functionality remains interoperable. This is explained in a short talk by Tim Berners-Lee called Linked Data is Like a Bag of Chips.
  • Even if individual developers cannot overcome the discrepancies in Lexicons during development, there could be some way for users and developer tools to solve them at runtime. This is what I call “Lens-based Interoperability”, and it’s inspired by Ink&Switch’s Cambria essay. Potentially, this could even be automated or AI-assisted to achieve Interoperable Serendipity.
10 Likes

This is why Lexicon Community exists - to help promote and support collaboration around the creation and use of shared community lexicons.

There is a mindset of data lexicons. It comes from adoption not pre-specification.

See https://lexicon.community for the new website.

See https://lexicon.garden for lexicon discovery and documentation.

On lenses, see Panproto https://panproto.dev/

@ngerakines.me is going to do some writing on “extending”. Short answer - you can just add records as you like, or you can emit sidecar records.

4 Likes

My position on extensions: Extensions field in records for third-party usage · bluesky-social/atproto · Discussion #1889 · GitHub

In short, we can make it work like a normal type system by storing the supertypes as type-keyed entries under $extension but this can have exponential space increase if a type is repeatedly forked and merged unless a DAG-shaped format is used. So, I guess, you’d have to allow $extensions entries to reference other $extensions entries. (edit: No, In this context, the dag structure can be expressed just with a tree of lists and type-value pairs, since the types can be used to make it clear when a particular supertype has been omitted/deduplicated, upcast would then be able to find the rootmost sibling that has that type and to link that in its place. You could also usually get away with representing the supertypes as a flat array of type-value pairs.)

You could also just put arbitrary type-keyed components in that extension field and treat it like an entity system.

(but when I see this stuff, I just come to the conclusion that we shouldn’t be building anything on top of a format like json that can’t naturally express dags, and in fact, there are also indications that we need cycles, for defining permissioning: the owner of an owner list is generally itself. And this is just what I can see, there are probably a whole lot of use cases that we can’t see.)

2 Likes

Thanks, I didn’t know about those initiatives, I’ll check them out!

Thanks for pointing towards that, I’ve added my thoughts on this in the discussion.

That extensions discussion is 3 years old and unlikely to go anywhere in that thread.

@noeldemartin.com: Technically, the protocol already supports having this type of extensions. For example, we could just have related records pointing to the base record that extend the functionality.

Yes, we call them sidecars. @ngerakines.me is going to do a write up around them soon

3 Likes

We should probably be calling them subclasses.

One issue I see with that is that in most Object Oriented languages, subclasses cannot be combined (meaning, no multiple inheritance). So that could create the incorrect mental model.

I do like “extensions” more, or “traits” as I mentioned in the github discussion, etc.

In any case, for people who don’t want to go to click through the github discussion, here’s a TLDR of what I think is most important for these:

  • They could be client-to-client specs/best practices/recommendations (no need to change the protocol, though we could in order to improve performance and ergonomics).
  • Extensions should be namespaces (in the same ways that Lexicons are, probably with NSID as well to remain consistent).

Since sidecars are just records, that method of extension does have this property automatically.

If you’d like to avoid backlink indexing to find sidecars, you can specify identical rkeys instead, but then a sidecar collection can extend only records in one specific target collection. On the plus side, it reduces space overhead somewhat.

I’m looking forward to that. I feel like they’re pretty under-utilised, even though they’re the cleanest and in theory most robust method of associating extra data.

3 Likes