// Last week we introduced the concept of a Recipe, a defined way to capture the same experience using the same set of statements across Activity Providers. This post will delve a bit further into how we got to the concept and the technical specifics about implementing them.

The “missing” data model

As thought leaders in a rapidly progressing community, we’ve tasked ourselves with trying to figure out what the next thing is that the community will want, or more importantly need, to effectively work with the Experience API. As the specification approached a 1.0 release, it became apparent that switching the identifiers for Verbs and other Statement parts to URIs was going to leave a gap. Out of that recognition came the Registry. The Registry provides a place for users of the Experience API to catalog the various terms they use to construct Statements.
A year later we realized another gap existed—the Experience API provides a ton of flexibility, but even the early adopters (innovators in their own right) were having issues implementing effective solutions with so much flexibility. They had too much proverbial rope with which to hang themselves.

The Experience API specification was intentionally limited to the communication and structure of data, but not the content of the data itself. As users get over the hump of dealing with a web service API, the concept of a Statement stream, and the anatomy of ever more complex Statements themselves, they look for how to combine those elements to aggregate data to reach conclusions which we’ve so emphatically told them that they’d be able to have. This is difficult with a single Activity Provider, but can become much more difficult when trying to interoperate experiences across multiple Activity Providers. There was an apparent lack of data model.
Re-enter the Registry.

The next piece of a Profile

We wrote about the concept of Profiles a while ago, but little has materialized around them. When we built the Registry, we included the ability to make a profile request and to create Activity identifiers under the URI space provided by a Profile. We hoped (and still do) that this would spur people into making well formed Activities with resolvable metadata and full Definitions. Shortly thereafter, we added the ability to link the other kinds of terms to a Profile, and for both sets of items to include a usage description. The next logical step was to put the two together with a set of instructions on how to build statements.

The technical side

A Recipe is both the concept that we’ve introduced, as well as a concrete representation of that concept that an Activity Provider uses to announce its intentions to systems reading the Statement stream. In practice, a Recipe builds on existing structure. It is an Activity, one with a specific Activity Type and place in a statement. In version 1.0.0 of the specification a ‘category’ property was added to the Context Activities, it is described as:

Category: an Activity used to categorize the Statement. “Tags” would be a synonym. Category SHOULD be used to indicate a “profile” of xAPI behaviors, as well as other categorizations. For example: Anna attempts a biology exam, and the Statement is tracked using the CMI-5 profile. The Statement’s Activity refers to the exam, and the category is the CMI-5 profile.

When creating a new Recipe in the Registry, an Activity will be automatically created under a specific namespace of the profile. That Activity ID then should be used in all statements for that Recipe. Systems doing reporting on the Statement stream can easily detect Statements with the specific Activity or can choose to query the learning record store’s Statement stream using the Activity ID directly. An example Recipe Activity will look like:

{
    "id": "http://id.tincanapi.com/recipe/checklist/performance-observation/1",
    "definition": {
        "type": "http://id.tincanapi.com/activitytype/recipe",
        "name": {
            "en-US": "Recipe: Checklist Performance Observation (v1)"
        },
        "description": {
            "en-US": "A recipe for recording the observation of someone's performance as a check list including a pass/fail indication for individual items and overall pass/fail. (v1)"
        }
    }
}

This is the Activity for a Recipe that we’ve populated in the Registry as a first example. Note that in the Definition we’ve assigned its ‘type’ as a special Activity Type that we coined in the Registry, namely “http://id.tincanapi.com/activitytype/recipe”. Statements contributing to a Recipe can be easily identified based on this special type.

Create Your Own

Creating a new Recipe is a simple process, but the structures should be thought out thoroughly before being published. Once a Recipe has been published, there could be people building applications using the instructions provided in the Recipe. The concept of a Recipe means that anyone can create one simply by establishing a new Activity with the special type, and using that Activity within the ‘category’ property of statements. Naturally we hope you’ll create them on the Registry and we’ve made it a simple process to do so.
1) Sign up for a free account
2) Request a profile to be created
3) Use the “Add” button in the toolbar and follow the instructions
4) Create any necessary activities or link other terms to the profile
5) Populate the markdown based instruction field
We’ve created two recipes to start, the aforementioned “Performance Observation Checklist” and a “Video” recipes. We’ll be following up this post in the coming weeks with additional posts about tools we’ve created for these two Recipes. If you are technical, and/or just chomping at the bit, you can see them in our open source repo.
If you want to talk about Recipes further or have questions, as always give us a shout via our Talk page, email to support@tincanapi.com, or @projecttincan or @k95bm01 on the Tweeter.

Brian Miller is the Senior Director of Engineering and is also the most pedantic person at the office, which is saying something. That skill makes him great at ensuring our products support the standards, which is precisely what he spends his days doing. Brian is a IEEE LTSC voting member working on the advancement of learning standards, like xAPI and cmi5.