Mar 05 2010

Amazon Products in KRL: A New Distribution Model

The first Web service that Amazon put up, years ago, was the ECommerce API that allowed API access to Amazon's product information. That API has gone through several name changes and is now called the Product Advertising API. Thousands of people have used this API to add data about products--and the opportunity to buy them--to their Web sites.

That's the problem, of course. You can use it on your Web site, but you can't conveniently use them in a browser extension to build client-side community apps because your Amazon developer keys would be exposed to the world. The most recent build of KRL changes that by making the Amazon Product Advertising API (PAA) available as a library. That means that it's possible to use Kynetx to build client-side applications that use the PAA without exposing your developer tokens. That opens up a whole host of possible uses for Amazon product information that were difficult to achieve before.

Here's a video that shows this at work:

Of course, to create client-side applications that people will install and use requires more than just pumping more product at them. The KRL integration of PAA includes the ability to access all the user-generated reviews, product information, photos, and other product data that would allow a developer to create a first-rate experience that adds real value for people who download and use their apps.

KRL makes using PAA easy. To get started, you simple put your Amazon developer secrets and associate ID in the meta block of your application:

meta {
  key amazon {
    "token"        : "absjj99a9ad9ad8799",
    "secret_key"   : "absjj99a9ad9ad87799absjj99a9ad9ad8799",
    "associate_id" :  "windleyofente-20"
  }
}

These are stored securely in the cloud and not divulged to users of the application.

The KRL Amazon library has two primary methods: ItemSearch and ItemLookup. With ItemSearch the search index is a parameter and additional parameters depend on the particular index. ItemLookup takes an Amazon product ID (ASIN) as it's primary parameter. Here's an example:

amazon:item_lookup({"ItemId" : "B00008OE6I",
                "response_group" : "ItemIds" })

The response is returned as JSON so that you can use JSONPath to pick it apart and use it. Here's a piece of the response to the previous query:

"Item" : {
            "OfferSummary" : {
               "LowestUsedPrice" : {
                  "Amount" : "3999",
                  "CurrencyCode" : "USD",
                  "FormattedPrice" : "$39.99"
               },
               "TotalRefurbished" : {},
               "TotalUsed" : "8",
               "TotalCollectible" : {},
               "TotalNew" : {}
            },
            "ASIN" : "B00008OE6I"
         }

Here's a video showing a little more about how this is done and giving a working example.

You can install the example that we used for the first video or just view the source code using the app detail page in the Apps Directory.
Here's the documentation for the Amazon library.

The Amazon integration with KRL allows Amazon developers to build client-side application that use Amazon product data without exposing the Amazon developer credentials--something that's been hard in the past. KRL is designed to make using online data like Amazon or Twitter easy and quick. We'll be annnouncing some other major data and service integrations over the next few weeks as we gear up for Kynetx Impact in April. Come join us.

Mar 03 2010

Building Fourth Party Apps with Kynetx

Doc Searls uses the term "sewage pump" (I'm paraphrasing) to describe the modern advertising-based economy. Modern society has created the most efficient machine imaginable to push stuff at people whether they want it or not. I gave an example in this blog post about Novatel: they're treating Twitter as a way to push stuff at me instead of as a place to relate to me.

A pump pushing sewage at you is a good metaphor for what's wrong with the marketplace we've constructed in the late 20th century. Doc has built the VRM project as a means of exploring better ways of building markets for the 21st century. Something I hadn't considered until I was going through David Siegel's book Pull is that "pull" is the right metaphor for this new marketplace and it's precisely why Doc's metaphor of a sewage pump rings so true.

David's book is about the Semantic Web and the use of data standards to enable you to "pull" the information, services, and products to you. An example from the book that really hit home for me is this: in 2010 if you order a package from Amazon, you have to give an address where it will be delivered. Wouldn't it be better if instead, you just gave Amazon an identifier and then the package would find you at the place you wanted it to go--even if that's the hotel you're currently staying at? In essence, you pull the package to you with online data. This isn't a pipe dream, but a perfectly reasonable way to think about how the world ought to work--and one that's doable now from a technical standpoint.

Doc uses different language to describe this same idea when he talks demand leading supply. The pump is all about supply leading demand. The key idea that both Doc and David would agree on here is that "If demand leads supply..., customers need to be the points of integration for their own data." More on that later.

The Four Party System

In an effort to further define VRM, Doc has introduced the notion of "fourth-party services." He says:

Among numbered parties the best-known one today is the third party. Wikipedia currently defines a third party this way (at least for the computer industry):

  • Third-party developer, hardware or software developer not directly tied to the primary product that a consumer is using
  • Third-party software component, reusable software component developed to be either freely distributed or sold by an entity other than the original vendor of the development platform

In general, a third party works on the vendor's side of the marketplace. However, the vendor is not generally called the "first party" (except in the game business, as Wikipedia says here). In fact, the most common use of the term "first party" in business is with insurance, where the term refers to the insured. (The insurer is the second party.)

From » VRM and the Four Party System ProjectVRM
Referenced Fri Feb 26 2010 11:04:37 GMT-0700 (MST)

So, if third-party services are merchant driven, it stands to reason that the customer-drive services that represent them would be the fourth party.
Here's a picture of these four parties:

The little horseshoe magnet looking things are called rel buttons are meant to represent customers or merchants (left and right in the above diagram) who want to relate to each other.

Fourth-party services, be theysimple or sophisticated will act as brokers that work on the user's behalf to manage their interaction with vendors of various products and services. Without such automated agents, no one would want to take on the work that would be necessary otherwise to manage the dozens of relationships each of us has with vendors. But with them magic happens.

Building 4th Party Apps

Doc and David are both thinking about very general solutions to this problem as well they should. My job, as the CTO for Kynetx, however, is slightly different. I'm trying to build things for our customers and make them work now. The Kynetx platform has always been aimed at creating client-side Web applications that help users achieve a purpose. That's a pretty good working definition of "fourth-party" in my book. The platform is designed to allow developers to use data in context to create interesting Web applications. Moreover, our corporate philosophy has been consistently in favor of respecting user rights to control data.

With that backdrop, I've thought long and hard about how Kynetx could be used in service of VRM and--by David's definition--the semantic web. I'll use this schematic to help explain my latest thinking:

To keep this simple, I'm going to avoid going down every "or they could do..." fork in the tree. There are lots of them. Here's the flow:

  1. The user visits a merchant. This could be online or in person (imagine the app running on their phone and using location in context).
  2. At the same time any fourth party apps that they've installed (denoted by the fourth-party rel-button) are invoked as long as they are relevant to the current activity.
  3. KNS (the Kynetx Network Service) executes the rules associated with the presented apps. We're going to presume for sake of this example that those apps need personal data to work on the user's behalf and such access has not been previously granted.
  4. KNS requests the required user information from the personal data store (PDS).
  5. The user is asked to authorized such access and grants it.
  6. The PDS requests the data from various sources as necessary and returns it to KNS. Note that as envisioned here, the PDS acts more like a virtual directory than an actual repository, although that's not a strict requirement.
  7. KNS executes any relevant merchant rules (determined by the app, current context, and the data retrieved in step 6) to determine how they want to relate. Merchant rules are denoted by the third-party rel-button in the diagram. This may be specific offers, discounts, special service levels, etc. I'm calling this "the deal" for lack of a better word.
  8. Finally the results are presented to the user's client.

A key feature of the scenario shown in the figure is the privacy wall (in red). That's there to reinforce the fact that in this model the user's data is never given to the merchant. The merchant's rules act against it, but they never see it. For fourth-party apps to work, users will need assurance that their data is being treated in a way that respects privacy. They will also need to trust the agents working on their behalf.

A few other points to note:

  • Kynetx has no access to user data except as authorized by the user. The user is entirely in control of the experience and what data is used.
  • The merchant rules could exists in a standard rule format like RuleML and be stored in any repository so long as they were discoverable.
  • The same holds for user data. There's no need for it to be in a single place as long as it's in standard formats, is discoverable, and has a clear, unambiguous meaning. David calls this same concept the personal data locker and it is central to the whole idea of the semantic web, pull, and VRM.
  • As envisioned the merchant rules, users data, and user apps are all orthogonal to each other. This isn't a single application, but a platform where fourth-party apps can be built using whatever user data and merchant rules are available.
  • Successful fourth-party apps won't just be ways to get offers to customers but manage the relationship between merchants and users in sophisticated ways. They could, for example store receipts, initiate and mediate support issues, manage returns, and so on.
  • In this demo, we're using OAuth to enable user control of the data in the PDS but that's really a stand-in for other more versatile standards that are forthcoming like UMA and R-Cards.
  • The scenario above focuses on one interaction where the app and the merchant rules could conduct a complete, complex negotiation on the user and merchant's behalf. Keep in mind, however, that the key is the relationship and that is bigger than a singleton deal or negotiation and might include support and service functions, ratings, and so on. Successful fourth-party apps will be seen by users as trusted agents, not merely a way to get a good deal on a single transaction.

A key difference between this model and a traditional ad network is the idea of "pull." Ads are not being pushed (note that successful pushing requires "tracking" and "targeting" users--niether is being done here). Rather more holistic information about what I'm calling "deals" is being pulled to the user based on their purpose and intent.

I have a working demo of all of this right now that uses a PDS that has access to a user's Amazon wish lists as an example of intent data and Acxiom-held data as an example of personal data--all under user control. Getting from demo to production is more a legal and business matter, not a technical one. We're working on that too. I plan to share this demo and the ideas and techniques behind it at the Kynetx Impact conference in April and at IIW X in May.

The inclusion of intent data in the demo is important because data that signals user intent or purpose is much more useful in creating compelling fourth-party apps than mere facts like gender or household size that leave the app to infer intent. Guessing will become less necessary because users will have convenient, private means of sharing intent. In this model, attention gives way to intention just as purpose gives way to location.

Some might complain that there's too much dependence on KNS or that KNS is closed. That's not technically true: Kynetx is proprietary, not closed. Still, if that bothers you, give me the standards and we'll use them. We're all about building support for standard data sources and formats into the system. As I mentioned above, I'm open to supporting rules expressed in RuleML or some other standard format. And, of course, no one is imagining that KNS would be the only system doing this. This is just our contribution to making the idea of VRM and fourth-party services real.

We invite your participation. Signup for a free developer account. Register for Impact where you can listen to Jon Udell's keynote and discuss these ideas with us. We're happy to listen, resolve issues, and make this work.

Feb 08 2010

KRL Build 424: Functions and Array Operators

Kynetx Logo

The latest build of the Kynetx Rule Language (KRL) provides a significant upgrade in capability with the addition of functions. We've also added some new array operators that take advantage of functions to make using arrays easier.

KRL supports functions as first-class objects in the expression language. KRL supports only anonymous functions, but they can be given names by binding them to a variable in a declaration. Here's an example:

pre {
  add5 = function(x) {
           x + 5
         };
}

Functions are evaluated statically (e.g. the environment they are defined in, not the environment they are executed in determines the binding of free-variables) and can be recursive. Here's an example of a recursive function in KRL:

pre {
  fact = function(n) {
            (n <= 0) => 1
                      | n * fact(n-1)
         }
}

Functions are declared using the keyword function and contain optional declarations followed by a single expression that returns the result of the function when executed. To see this,
consider the following example which uses Newton's method to calculate square roots (taken from Section 1.1.8 of Structure and Interpretation of Computer Programs):

sqrt = function(x) {
    average = function(x,y) { (x + y) / 2 };
    good_enough = function(guess, x) {
       v = (guess * guess) - x;
       v < 0.01 && v > -0.01
    };
    improve = function(guess, x) {
       average(guess, (x / guess))
    }
    sqrt_iter = function(guess, x) {
       good_enough(guess, x) => guess
                              | sqrt_iter(improve(guess,x), x)
    };
    sqrt_iter(1.0, x)
}

Functions can return functions as values and functions can be passed as the arguments to other functions and operators in KRL. The following example defined a generalized summation function that sums the numbers from a to b incrementing using inc and applying the function f to each term:

sum = function(f, a, next, b) {
  (a > b) => 0
           | f(a) + sum(f, next(a), inc, b)
};
inc = function(x) { x + 1 };
cube = function(x) { x * x * x };
sum_cubes = function(a, b) {
  sum(cube, a, inc, b)
}

We could define a function that creates incrementor functions. When given a number, it returns a function that increments by that value:

inc_generator = function(n) { function(x){ x + n } };
inc = inc_generator(1);
inc_by_2 = inc_generator(2);
inc_by_25 = inc_generator(25);

Being able to write functions adds significant power. More so with some of the other languages changes we have in mind for the next few months.

Weve also added several new array operators in recent builds. Most notably, array references now work as follows:

a = [1,4,3,6,5];
b = a[1]

This would bind the value 4 to the variable b. Note that array references only work for arrays of one-dimension, so c[1][2] is not allowed (presuming c is an array of arrays).

In addition, there are a number of new operators available for arrays.
The following array operators are now available (in addition to length which has been previously available):

  • sort - sorts the array. With no argument, sorting is done in ascending order. The argument "reverse" causes sorting to happen in descending order. The argument can also be a function that takes two argument and returns a boolean value which will be used as the comparison function for the sort.
  • filter - filters an array, producing a new array. The operator takes a function argument that takes a single parameter and returns a boolean value. The return array contains elements for which the function returns true.
  • map - modfies an array from mapping a function to each member of the array. The operator takes a function argument that takes a single parameter and returns any value. The array returned from map is the result of applying the function to each member of the original array in turn, collecting the results into a new array.
  • head - returns the first element of an array without modifying the array.
  • tail - returns an array that is identical to the orginal array except without the first member.

You could use these like so:

pre {
  f = function(x) { x < 4 };
  g = function(y) { y * 2 };
  a = [1,4,3,6,5];

  b = a.sort(); // returns [1,3,4,5,6]
  c = a.filter(f); // returns [1,3]
  d = a.head(); // d has the value 1
  e = a.map(g); // e has the value [2,8,6,12,10]
}

Operators are fairly easy to add and handy to have, so if you have ideas for other operators, on arrays, strings, and so on, just let us know.