With two toddlers at home, I’m fairly used to short, choppy sentences as a manner of communication. I have whole books filled with them, granted they are only about 15 pages long with type even my grandfather can see. And while most of the time I can get my point across, and usually even so can the toddler, and the books are certainly appealing (to at least one of us), I am excited for my daughters to get to explore the richness that is language, particularly one as “colorful” as English. The same can be said of Experience API exploration (though not necessarily by my daughters). While the Actor-Verb-Object structure is critical for a bare minimum of understanding, it is the context of the statement that gives it life and, dare I say beauty (okay, that’s a bit of a stretch even for me).
Although not required, most statements are going to need to include some additional context to convey the extent of their meaning. One way to capture additional meaning takes the form of a Context object placed in the ‘context’ property of the statement. All properties of the Context object are optional, and they may be mixed and matched as needed with only a few restrictions. There are nine Context properties ranging from the very specific ‘registration’ to the completely open ‘extensions’.
I’ve already touched on the ‘contextActivities’ property in the “Deep Dive: Activity” post. As mentioned there, the ‘contextActivities’ property takes an object as its value as well. This object has four optional properties itself, specifically ‘parent’, ‘grouping’, ‘category’, and ‘other.’ These properties take the same type of value, either a list (array) of Activity objects or a single Activity object. The Activity objects included in these lists form the relationships amongst Activities and provide structure to what would be otherwise isolated experiences. Placing an Activity in one of the ‘contextActivities’ properties allows it to be queried via the Statements API using the ‘related_activities’ parameter.
Using the ‘parent’ property generally implies that the Statement’s object is itself an Activity, specifically one that is a sub-Activity of a larger whole. The other properties have looser relationship qualities, but the specification does call out specific meanings for each. The ‘category’ property relates to a statement as being part of a “profile” such that it adheres to some known, expected use case. One application of this is to identify the source application that’s generating the statement so consumers of the data can recognise statements from different tools. The ‘grouping’ property allows statements to be associated based on their object’s Activity as part of a larger whole but without the direct subset correlation as with ‘parent.’ Finally, ‘other’ is for catching any other use cases not defined directly in the specification.
The ‘registration’ property has its roots in the LMS (Learning Management System) / SCORM world so is related to the concept of a registration there which is tied to when a learner is enrolled or enrolls for a particular experience. This property takes a UUID (or GUID) value as a string just like the ‘id’ property as covered in “Deep Dive: Extras/Others”. Fundamentally, it is in the specification to support the concept of identifying a specific instance of a person (or persons) having an experience which need not be recorded as a single statement and it is not restricted to be used in statements for a specific Agent or Activity. In the xAPI space, an experience may be captured with many statements from multiple points of view and be made up of numerous activities, the registration value then can be used to tie all of them together.
For example, in the xAPI Prototypes JS Tetris game, the top level Activity is consistent and a single Agent may play multiple games which generate numerous statements (one for each level reached, etc.); therefore it is not sufficient for us to look at statements for just the Agent and Activity combination to determine statements unique to a played game. We could try to piece the single game experience together based on a starting and ending statement and a range of timestamps, but this is overly error prone and a little too clever. Instead, each new game is assigned a registration which is included in the Context of the statements generated for that instance of the experience. This makes it possible to discern the set of statements making up a unique game amongst all of those played by a specific Agent using that Activity.
To facilitate the use case intended for ‘registration’ it is a property that is exposed via the Statements query API. In other words, a client can query the LRS directly for the statements that have a specific registration. Additionally, the registration concept can be applied to the State API as an optional component of what makes a document unique.
The ‘instructor’ property takes a value that is either an Agent or Group as covered in the “Deep Dive: Agent/actor” post. This value is fairly specific to learning experiences, the intended use case for Experience API after all, and will likely correlate to certain kinds of verbs. This property is hopefully self explanatory, though need not be confined to a “formal” instructor as informal training experiences occur commonly between two Agents. Statements with an ‘instructor’ property might read like: “Brian learned xAPI from Ben (instructor).”
The ‘team’ property requires a Group object as value. I’ll admit, I struggled with the meaning of this one so sought out advice from my team (turns out it was a team of one, but whatever). The key to the ‘team’ property’s meaning is that it is useful when a singular Agent (or subset of a Group) performs an action that is part of an experience where it is important to recognize the team as part of the context. For instance, during a car race a pit crew may constitute a team, but only one member is involved in refueling the vehicle during each stop, so a statement might be created for “Brian refueled Car 33 during pit stop 2 (performed by) team Red” where the “performed by” is inferred from the ‘team’ property having a value. In the training space, you could think of a team of physicians and nurses running a disaster drill where each has an assigned task, but each task contributes to the common objectives of a single team. Without a complete, cohesive set of tasks performed correctly by each member as the team as a whole the overall result of the exercise could be failure.
In “Deep Dive: object” I talked about Statement References. Statement References can be used as the ‘object’ of the statement, but in the case where another object, perhaps an Activity, makes more sense in that position a Statement Reference can still be used as context within the Context object’s ‘statement’ property. There was also a section of that post that talked about Sub-Statements and how they can be used to indicate a future event. As an example, the ‘statement’ Context property would be a great place to capture a reference to the original “planning” statement in statement(s) generated when the event finally occurs.
The ‘revision’ property takes a string value that has a free form value. Additionally, the specification precludes the use of this property when the ‘object’ of the statement is an Agent or Group. The value of this property is intended to capture small or minor edits made to an experience, where minor edits include typos or spelling errors. More significant edits, where meaning itself may have changed, should be handled through updates to Activity IDs, etc. It is important to remember that this ‘revision’ property is context for the statement rather than part of the definition of a single Activity. It has roots in the “packaged learning world” and is provided primarily to capture the small revisions where a package may change but an accompanying change to a new Activity ID was not required.
The ‘platform’ value takes a string as well, and equally free form, and again must not be used with an ‘object’ that is an Agent or Group. Because experiences, specifically learning activities, may be delivered in multiple ways this property is intended to capture information about how, or possibly where, the experience occurred. For instance, it might have been delivered via an “online course” or “in person” or perhaps via a “simulator.” It may be the case that these have different Activity objects with unique IDs, but it may also be meaningful to capture all of the ways that someone can experience the same learning objective such that the delivery method is merely context.
International interoperability is particularly important to the Experience API specification and the ‘language’ Context property provides a way to capture the language of the original experience when known and identifiable. The value for this property should be a string with an RFC 5646 formatted value, the same as the keys that make up the language maps used elsewhere in the specification, such as the ‘display’ property of verbs and the ‘name’ property of Activity Definitions. Combining those language maps with the ‘language’ context can provide a fuller picture of the actor’s experience.
The ‘extensions’ property may occur in a couple places in a statement, another place is the Activity Definition as mentioned in the “Deep Dive: Activity” post. Extensions warrant their own post which is coming soon, but essentially it is a catch all for any other context that could possibly be relevant to this specific statement. For some examples of Extensions for use in Context, check out registry.tincanapi.com.
The Context object provides such a varied set of values it is a shame to not include as much information in a statement as is possible. In these early days of Experience API adoption, the simple statements win out as it seems we are but mere toddlers exploring a new language, or at least a new way to structure our language. As adoption increases, so will the complexity of the experiences we are able to capture. I feel we’ve wished to capture them for a long time, now we are empowered to, and the harder task of drawing meaning from all the contextual elements still awaits us.
Go now, make statements!